C++中的类可以定义与类名相同的特殊成员函数,这种与类名相同的成员函数叫做 构造函数. 在对象被创建的时候,用来初始化对象的函数
自动调用:一般情况下C++编译器会自动调用构造函数. 手动调用:在一些情况下则需要手工调用构造函数.
C++中的类可以定义一个特殊的成员函数清理对象,这个特殊的成员函数叫做 析构函数.
析构函数的作用,并不是删除对象,而在对象销毁前完成的一些清理工作。 析构函数调用的顺序,跟构造函数相反,先构造的,后析构
由己存在的对象,创建新对象。也就是说新对象,不由构造器来构造,而是由 拷贝 构造器来完成。拷贝构造器的格式是固定的。
1.有参构造 2.无参构造 3.拷贝构造
注意场景4,5,6
有关 匿名对象的去和留 //如果用匿名对象 初始化 另外一个同类型的对象, 匿名对象 转成有名对象 //如果用匿名对象 赋值给 另外一个同类型的对象, 匿名对象 被析构
当类中没有 显示的无参,显示的有参,,编译器会默认提供一个无参构造函数,并且其函数体为空。 当类中没有 显示的拷贝构造,编译器会默认提供一个默认拷贝构造函数,简单的进行成员变量的值复制。 当类中没有 显示的析构函数,编译器会默认提供一个析构函数。
只要你写了构造函数,则必须要用
系统提供默认的拷贝构造器,一经定义不再提供。但系统提供的默认拷贝 构造器是 等位拷贝,也就是通常意义上的浅拷贝。如果类中包含的数据元素全 部在栈上,浅拷贝 也可以满足需求的。但如果堆上的数据,则会发生多次析构行为。
//=操作符 void operator=(const Name &another) { cout << “operatoer = (const Name &)” << endl; m_p = another.m_p; }
可以把 释放空间函数free() 放在析构函数里面,当程序结束时,自动调用,回收空间 或者自己写一个释放函数接口,最后自己再调用进行释放 void myFree(){ free(m_p); m_p = NULL; }
如果我们有一个类成员,它本身是一个类或者是一个结构,而且这个成 员它只有一个带参数的构造函数,没有默认构造函数。这时要对这个类成员进 行初始化,就必须调用这个类成员的带参数的构造函数, 如果没有初始化列表,那么他将无法完成第一步,就会报错。
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std; class A { public: A(int a) { cout << "A()..."<<a << endl; m_a = a; } ~A() { cout << "~A()" << endl; } void printA() { cout << "a = " << m_a << endl; } private: int m_a; }; //构造函数的初始化列表 class B { public: B(A a1, A a2, int b) : m_a1(a1), m_a2(a2) { cout << "B(A&, A&, int)..." << endl; m_b = b; } //构造对象成员的顺序跟初始化列表的顺序无关 //而是跟成员对象的定义顺序有关 B(int a1, int a2, int b) : m_a1(a1), m_a2(a2) //前后赋值顺序无关 { cout << "B(int, int, int)..." << endl; m_b = b; } void printB() { cout << "b = " << m_b << endl; m_a1.printA(); m_a2.printA(); } ~B() { cout << "~B().." << endl; } private: //声明顺序有关 int m_b; A m_a2; A m_a1; }; void test1() { A a1(10), a2(100); B b(a1, a2, 1000); b.printB(); } class ABC { public: ABC(int a, int b, int c, int m) :m_m(m) { cout << "ABC(int ,int int)" << endl; m_a = a; m_b = b; m_c = c; } ~ABC() { cout << "~ACB()" << endl; } private: int m_a; int m_b; int m_c; const int m_m;//常量 }; class ABCD { public: ABCD(int a, int b, int c, int d, int m) : m_abc(a, b, c, m), m_d(d) { } ABCD(ABC&abc, int d) :m_abc(abc) { m_d = d; } private: int m_d; ABC m_abc; }; int main(void) { B b(10, 20, 300); b.printB(); ABC abc(10, 20, 30, 666); ABCD abcd(1, 2, 3, 4, 666); ABCD abcd1(abc, 40); return 0; }**当类成员中含有一个const对象时,或者是一个引用时,他们也必须要通 过成员初始化列表进行初始化,**因为这两种对象要在声明后马上初始化,而在 构造函数中,做的是对他们的赋值,这样是不被允许的。
初始化列表中的初始化顺序,与声明顺序有关,与前后赋值顺序无关。
构造中调用构造是危险的行为,是不被允许的