《随笔五》——构造函数、析构函数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34536551/article/details/83537243

构造函数


●  构造函数的主要功能是: 为对象分配空间,也可用来为类数据成员赋初值。 该函数没有返回类型,不能有return语句;甚至 void也不行。

●  在实际应用中,一般都要给类声明和定义构造函数,如果没有声明和定义,编译系统就自动生成一个默认的构造函数,这个默认的构造函数不带任何参数,只能给对象开辟一个存储空间, 而不能为对象中的数据成员赋初值, 此时数据成员的值是随机的。

如果在类中显式声明了构造函数,无论是否有参数,编译器都不会再为之生成任何形式的构造函数, 如果你还需要不带参数的默认构造函数,可以手动声明一个。

● 默认构造函数是指不需要指定实参就能被调用的构造函数, 这并不意味着它不能接受实参。 只意味着构造函数的每个参数都有一个默认值与之关联。

         以下函数都是默认的构造函数
	Time() {} 没有参数的构造函数
	   参数被指定的默认构造函数
	Time(int size = 9){}
	Time(double re=5.2,double im=0.5){}

注意: 对象所占据的内存空间只是用于存放数据成员, 成员函数不在每一个对象中存储副本。

●  下面看一个数据成员被初始化的程序:

class Time
{
public:
	unsigned short hour;
	unsigned short minute;
	unsigned short second;
	const char *ptr;
};
int main()
{
	Time myTime = { 100,200,300 ,"huang"}; 用显示初始化列表初始化公有的数据成员
	cout << myTime.hour << " " << myTime.minute << " " << myTime.second <<" " << myTime.ptr << endl;
	system("pause");
	return 0;
}

根据数据成员被声明的顺序,显示初始化列表中的值一一对应初始化。

如果这样初始化就错误:

Time myTime = { "huang",100,200,300 }; 用显示初始化列表初始化公有的数据成员

显示初始化列表有两个缺点: 它只能被应用到所有数据成员都是公有的类的对象上。它要求程序员的显示干涉,增加了意外(忘了提供初始化表) 和 错误(弄错了初始值顺序)的可能性。

在某些应用中,通过显示列表初始化,用常量值初始化大型数据结构比较有效。


限制对象创建


● 构造函数的可访问性由其声明所在的访问区来决定。 可以通过把相关的构造函数放到非公有访问区内, 从而限制或显式禁止某些形式的对象创建。

● 注意: 一般构造函数通常被声明为公有,如果是私有,那么在main函数中创建对象不能为其成员初始化, 因为没有访问权限。

如果说构造函数时私有的,那么该函数就不能被其他类或者全局函数所使用。而创建C++ 实例需要调用构造函数。 如果构造函数私有,除了类自己的方法外,其他类不能构造这个类的实例。所以,在一般情况下,构造函数是私有,其他类使用它就很困难了。

但是, 有时候不希望其他对象能够实例化一个类,就是这个类只需要一个实例的时候, 为了避免其他外部类创建多个实例的时候,通过把构造函数定义为私有的。


拷贝构造函数


●  该函数是一种特殊的构造函数,具有一般构造函数的所有特性,其形参是本类的对象的引用。  其作用是使用一个已经存在的对象去初始化同类的另一个新对象。

●  其形式为:

类名(类名 &对象名)
{
  //statement
}

注意: 其中 “&对象名 ” 表示对一个对象的引用, 该参数是一个已经初始化的类对象。该参数(对象的引用)是一个不可变的const类型。拷贝构造函数要调用基类的拷贝构造函数和成员函数。

如果没有定义类的拷贝构造函数,系统会在必要时自动生成一个默认的拷贝构造函数,该函数的功能是: 把已存在的对象中数据成员的值都一一对应复制到新建立的对象中。 因此,可以说完成了同类对象的创建, 两个对象中的数据成员的值相同,即完全相同的属性。


调用拷贝构造函数


● 一般来说,以下三种情况拷贝构造函数会被调用:

用类的对象去初始化该类的另一个对象时。

函数的形参是类的对象时,函数调用过程中进行形参和实参的复制时。

函数的返回值是类的对象, 函数执行完进行返回时。

下面看一个示例程序:

class Point
{
public:
	Point(int xx = 0,int yy = 0)
	{
		X = xx;
		Y = yy;
		cout << "构造函数被调用!" << endl << endl;
	}
	Point(const Point &p)
	{
		X = p.X; 为新创建的对象的成员赋初值
		Y = p.Y;
		cout << "拷贝构造函数被调用!" << endl << endl;
	}
	int getX() { return X; }
	int getY() { return Y; }
private:
	int X, Y;

};
void fun(Point pt)
{
	cout <<"输出fun 函数中的值"<< pt.getX() << endl << endl;
}
Point myFun()
{
	Point pt(1, 5); 调用构造函数
	return pt; 函数返回值是类对象,返回函数时,拷贝构造函数被调用
}
int main()
{
	第一种情况时
	Point A(2, 3); 调用构造函数
	Point B(A); 调用拷贝构造函数
	cout << B.getX() << endl << endl;

	第二种情况时
	Point C(5, 6);  调用构造函数
	fun(C);  函数的形参为类的对象, 当调用函数时,拷贝构造函数被调用

	第三种情况时
	Point D;
	D = myFun();
	cout << "输出对象D的X的值:" << D.getX() << endl << endl;
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_34536551/article/details/83537243