C++-对象和类(进阶)

对象和类(进阶)

(1)   类的构造函数和析构函数

1.     C++提供了一个特殊的成员函数-类构造函数,专门用于构造新对象、将值赋给它们的数据成员。

构造函数的原型和函数头有一个有趣的特征-虽然没有返回值,但没有被声明为void类型。 实际上,构造函数没有声明类型。

Stock(const std::string & co, long n = 0, double pr = 0.0);
该原型位于类声明的公有部分。
//构造函数定义
Stock::Stock(const std::string & co, long n, double pr)
{
	company = co;
	if (n < 0)
	{
		std::cout << "Number of shares can't be negative;"
			<< company << " shares set to 0.\n";
		shares = 0;
	}
	else
		shares = n;
	share_val = pr;
	set_tot();  
}

上述代码和前面的函数acquire( )相同。 区别在于,程序声明对象外,将自动调用构造函数。

注意:参数名不能与类成员相同。

比如: Stock::Stock(const std::string&company, long shares, double share_val);

是错误的。

1.     使用构造函数。

C++提供了两种使用构造函数来初始化对象的方式。 第一种方式是显式地调用构造函数。

Stock food = Stock("World Cabbage", 250,1.25);

另一种方式是隐式地调用构造函数。

Stockgarment("Flurry Mason", 50, 2.5);

构造函数地使用方式不同于其他类方法。 一般来说,使用对象来调用方法:

stock1.show();      //对象stock1调用show( )方法

但无法使用对象来调用构造函数,因为在构造函数构造出对象之前,对象是不存在地。 因此构造函数用来创建对象,而不能通过对象来调用。

2.     析构函数

用构造函数创建对象后,程序负责跟踪该对象,直到其过期为止。 对象过期时,程序将自动调用一个特殊地成员函数-析构函数。 和构造函数一样,析构函数的名称也很特殊:在类名前加上~。 另外,和构造函数一样,析构函数也可以没有返回值和声明类型。与构造函数不同的是,析构函数没有参数,因此Stock析构函数的原型必须是这样的:

~Stock( )

由于在类对象过期时析构函数将自动被调用,因此必须有一个析构函数。 如果程序员没有提供析构函数,编译器将隐式地声明一个默认析构函数,并在发现导致对象被删除的代码后,提供默认析构函数的定义。

(1)   改进Stock

1.     头文件:

改进:将构造函数和析构函数原型加入到原来的类声明中;删除了acquire( )函数;使用了#ifndef技术来防止多重包含。

//stock00.h -- 股票类接口,添加了构造函数和析构函数
#ifndef STOCK00_H_
#define STOCK00_H_
#include<string>
class Stock   //类声明
{
private:
	std::string company;
	long shares;
	double share_val;
	double total_val;
	void set_tot() { total_val = shares * share_val; }
public:
	//两个构造函数
	Stock();        //默认构造函数
	Stock(const std::string & co, long n = 0, double pr = 0.0);
	~Stock();       //析构函数
	void buy(long num, double price);
	void sell(long num, double price);
	void update(double price);
	void show();
};     //请注意结尾处的分号
#endif // !STOCK00_H_
2.	实现文件:
为了让您知道这些方法何时被调用,构造函数和析构函数都显示一条消息。
//stock00.cpp -- 实施股票类
#include<iostream>
#include"stock10.h"
//构造函数定义
Stock::Stock()            //默认构造函数
{
	std::cout << "Default constructor called\n";
	company = "no name";
	shares = 0;
	share_val = 0.0;
	total_val = 0.0;
}
Stock::Stock(const std::string & co, long n, double pr)
{
	std::cout << "Constructor using " << co << " called\n";
	company = co;
	if (n < 0)
	{
		std::cout << "Number of shares can't be negative;"
			<< company << " shares set to 0.\n";
		shares = 0;
	}
	else
		shares = n;
	share_val = pr;
	set_tot();  
}
//析构函数
Stock::~Stock()
{
	std::cout << "Bye, " << company << "!\n";
}
void Stock::buy(long num, double price)
{
	if (num < 0)
	{
		std::cout << "Number of shares purchased can't be negative."
			<< "Transaction is aborted.\n";
	}
	else
	{
		shares += num;
		share_val = price;
		set_tot();
	}
}
void Stock::sell(long num, double price)
{
	using std::cout;
	if (num < 0)
	{
		cout << "Number of shares purchased can't be negative."
			<< "Transaction is aborted.\n";
	}
	else if (num > shares)
	{
		cout << "You can't sell more than you have!"
			<< "Transaction is aborted.\n";
	}
	else
	{
		shares -= num;
		share_val = price;
		set_tot();
	}
}
void Stock::update(double price)
{
	share_val = price;
	set_tot();
}
void Stock::show()
{
	using std::cout;
	using std::ios_base;
	//将格式设置为#.###
	ios_base::fmtflags orig = cout.setf(ios_base::fixed, ios_base::floatfield);
	std::streamsize prec = cout.precision(3);
	cout << "Company: " << company
		<< " Shares: " << shares << '\n';
	cout << " Share Price: $" << share_val;
	//将格式设置为#.##
	cout.precision(2);
	cout << " Total Worth: $" << total_val << '\n';
	//恢复原始格式
	cout.setf(orig, ios_base::floatfield);
	cout.precision(prec);
}

3.     客户文件

//usestock0.cpp -- 客户程序
//和stock10.cpp一起编译
#include<iostream>
#include"stock10.h"
int main()
{
	{
		using std::cout;
		cout << "Uisng constructors to create new objects\n";
		Stock stock1("NanoSmart", 12, 20.0);           //语法1
		stock1.show();
		Stock stock2 = Stock("Boffo Objects", 2, 2.0);  //语法2
		stock2.show();
		cout << "Assigning stock1 to stock2:\n";
		stock2 = stock1;
		cout << "Listing stock1 and stock2\n";
		stock1.show();
		stock2.show();
		cout << "Using a constructor to reset an object\n";
		stock1 = Stock("Nifty Foods", 10, 50.0);
		cout << "Revised stock1:\n";
		stock1.show();
		cout << "Done\n";
	}
	std::cin.get();
	return 0;	
}

(3)   构造函数和析构函数小结

构造函数是一种 特殊的类成员函数,在创建类对象时被调用。 构造函数的名称和类名相同,但通过函数重载,可以创建多个同名的构造函数,条件是每个函数的特征标(参数列表)都不同。另外,构造函数没有声明类型。

就像对象被创建时程序将调用构造函数一样,当对象被删除时,程序将调用析构函数。 每个类都只能有一个析构函数,析构函数没有返回类型,也没有参数,其名称为类名称前加上~





猜你喜欢

转载自blog.csdn.net/ezra1991/article/details/80900620