创建对象时自动调用
if 类中没有定义任何一个构造函数
编译器会自动合成一个默认构造函数
else 写了构造函数
编译器不会合成一个默认的构造函数
if 定义了不带参数或各参数均有默认值的构造函数
C++编译器都认为其是默认的构造函数。
//1 Student(void) { m_age = 0; m_sex = ‘m’; } //2 Student(int age = 0, char sex = ‘m’, string name = “”) { m_age = age; m_sex = sex; m_name = name; }创建对象
student stu1;//上面两个都能调用,所以1、2两种一起写,会报错
//3 Student(int age, char sex = 'm', string name = "") { m_age = age; m_sex = sex; m_name = name; } Student stu1(18); Student stu2(18, 'f'); Student stu3(18, 'f', "zhangsan"); 上面三种创建对象都可以调用3有默认值的写后面不要写成下面4这种
//4 Student(int age = 18, char sex, string name) { m_age = age; m_sex = sex; m_name = name; } Student stu1('f', "zhangsan");//默认给前两个,会报错类名 对象名; ===》调用默认的构造函数 ===》调用无参构造函数 或者 调用带参数但是参数设有默认值的构造函数
类名 对象名(); //没有这种方式,编译器认为是函数的声明; Student stu1();//编译器将类对象stu1的定义理解为一个函数的声明,该函数不接受参数并返回一个Student类型的对象.
类名 对象名(属性参数); ===》调用带参的构造函数
初始化是指创建对象的同时给它赋初值,赋值是擦除对象的当前值并用新值代替。
初始化列表是执行初始化过程,在创建数据成员的同时给它们赋初值。在构造函数体中赋值是执行赋值过程,数据成员在执行函数体之前就已经创建,有一个值,在函数体里重新赋给数据成员新的值。
Student::Student(int age, string name, char sex): m_age(age), m_name(name), m_sex(sex) { }
没有显式定义复制构造函数,编译器会自动合成一个复制构造函数; 类的复制构造函数执行的操作就是用同类型的对象给新创建的对象初始化的过程。
类名 对象名(已经构造的同一类型对象参数); ===》调用复制构造函数 称为:类对象的复制(对象创建同时赋初值)类名 对象名 = 已经构造的同一类型对象; ===》调用复制构造函数 称为:类对象的复制(对象创建同时赋初值) //形参要用引用& Cperson(const Cperson &orig):name(orig.name), age(orig.age), salary(orig.salary){ cout << "调用复制构造函数" << endl; }注意点:当类中有成员是指针变量时或者在类中有动态分配内存的情况发生,必须显式的定义自己的复制构造函数,否则在复制过程中容易产生错误。
没有显式定义赋值操作符重载函数,编译器会自动合成一个赋值操作符重载函数,按照类中定义的顺序,按每个成员的赋值操作符依次对每个成员进行赋值。
赋值操作符重载函数执行的操作是擦除已存在对象的内容,给这个对象赋新的值。
已经构造的对象A = 已经构造的同一类型对象B; ===》调用类的赋值操作符重载函数 称为:类对象的赋值(对象已经被创建)撤消类对象时自动调用
一个类只能有一个自定义的析构函数,不能重载;
不管是否显式的定义了析构函数,编译器都会自动的合成一个析构函数。
class Student{ int m_age; string m_name; char m_sex; }; //合成的析构函数按照数据成员创建时相反的顺序来释放这些成员。从下往上(栈) ~Student(){ //code //delete } //对于类类型的数据成员,合成析构函数调用该类的析构函数来撤消此成员注意:有动态内存的申请和释放,必须定义析构函数释放内存,必须定义复制构造函数和赋值操作符重载函数,来申请副本的动态内存,避免两个对象的指针成员操作同一块内存的情况。