1、构造函数、拷贝构造函数
如果不写任何构造函数,编译器会自动添加:默认的构造函数、默认的拷贝构造函数。
如果自定义了一个构造函数,而没有自定义拷贝构造函数,编译器会自动添加:默认拷贝构造函数。
如果自定义了一个拷贝构造函数,而没有自定义构造函数,编译器不会添加默认的构造函数。此时因为没有任何普通构造函数,无法定义一个实列对象。因此只定义一个拷贝构造函数是没有意义的,还需要至少自定义一个普通构造函数。
综上,合法的情况如下:
(1)不自定义任何构造;由编译器添加:默认构造、默认拷贝构造。
(2)自定义:普通构造;由编译器添加:默认构造。
(3)自定义:普通构造、默认构造。
有构造/拷贝,不自动构造;
有拷贝,不自动拷贝;无拷贝,有自动拷贝。
当不定义任何构造函数时,使用默认的构造函数时,可以使用对象的初始化列表来初始化 public 变量。默认构造函数相当于一个按顺序给 所有public变量 赋值的构造函数。
当不定义拷贝构造函数时,使用默认的拷贝构造函数时,可以进行浅拷贝。默认拷贝构造函数相当于一个按顺序给 所有变量 赋值的构造函数。
2、成员:
有const变量、引用变量时,需要自定义构造函数,用列表初始化。这两种变量必须用构造函数在定义的时候初始化,不能调用普通的成员函数初始化。
有指针变量、引用变量时,并且有拷贝操作(用其它对象赋值、传对象、返回对象)时,需要自定义拷贝构造函数。
3、对象数组:
可以进行列表初始化,甚至在列表里调用构造函数初始化。
初始化列表实际上是调用构造函数来初始化的。因此,如果没有自定义任何构造函数,初始化列表调用的是默认的构造函数,只能对公有成员进行初始化;如果自定义了构造函数,初始化列表会调用自定义构造函数,对成员进行初始化。
(1)直接传数值
class exam {
int x;
public:
exam(int n) { x=n; }
int get_x() { return x; }
};
int main()
{
exam ob[4]={ 11, 22, 33, 44 };
for (int i=0;i<4;i++)
cout << ob[i].get_x( ) << ' ';
return 0;
}
(2)调构造函数
class exam {
int x;
public:
exam(int n) { x=n; }
int get_x() { return x; }
};
int main()
{
exam ob[4]={ exam(11), exam(22), exam(33), exam(44) };
for (int i=0;i<4;i++)
cout<<ob[i].get_x( )<<' ';
return 0;
}
(3)前两个调带一个参数的构造函数,后两个调不带参数的构造函数
class exam {
int x;
public:
exam() { x=123; }
exam(int n) { x=n; }
int get_x() { return x; }
};
int main()
{
exam ob[4]={55,66}; // 55 66 123 123
int i;
for (i=0; i<4; i++)
cout << ob[i].get_x() << ' ';
return 0; }
(4)传多个参数
class Rectangle{
public:
Rectangle(int len=10, int wid=10)
{
length=len;
width=wid;
}
int area()
{
return(length*width);
}
private:
int length, width;
};
int main()
{
Rectangle rec[3] = { Rectangle(10,20),
Rectangle(30,40),
Rectangle(50,60) };
//Rectangle rec[3] = { {10,20}, {30,40}, {50,60} }; //直接传数
cout<<"The area of rec[0] is "<<rec[0].area()<<endl;
cout<<"The area of rec[1] is "<<rec[1].area()<<endl;
cout<<"The area of rec[2] is "<<rec[2].area()<<endl;
return 0;
}
4、析构函数
如果没有在类中定义构造函数,则编译系统自动地生成一个默认的构造函数。这个默认的构造函数,不带任何参数,只能为对象开辟一个存储空间,而不能给对象中的数据成员赋初值。
(1)构造函数 new 动态内存,需要深拷贝,需要在析构中释放 delete 内存
(2)虚函数
(3)如果一个对象被定义在一个函数体内,则当这个函数结束时,该对象的析构函数被自动调用。
(4)若一个对象是使用new运算符动态创建的,在使用delete运算符释放它时,delete会自动调用析构函数。