C++中的构造函数和析构函数
基本概念
构造函数总结 构造函数是C++中用于初始化对象状态的特殊函数 构造函数在对象创建时自动被调用(默认调用),隐身调用 构造函数和普通成员函数都遵循重载规则 拷贝构造函数是对象正确初始化的重要保证 必要的时候,必须手工编写拷贝构造函数 |
构造函数的调用 自动调用:一般情况下C++编译器会自动调用构造函数 手动调用:在一些情况下则需要手工调用构造函数 |
构造函数有三种 |
有参构造函数、默认构造函数、拷贝构造函数 |
析构函数 |
有参构造函数调用的三种方法
// class Test { public: //有参构造函数 Test(int a) { m_a = a; } //无参数构造函数 Test() { m_a = 0; } //四种应用场景 //赋值构造函数 copy构造函数 Test(const Test &obj) { } public: void print() { cout<<"m_a"<<m_a<<endl; } protected: private: int m_a; }; void main66() { //括号法 Test t1(10); //c++编译器自动调用这个类的有参构造函数 t1.print(); //= Test t2 = 20; //c++编译器自动调用这个类的有参构造函数 t2.print(); // Test t3 = Test(30);//程序员手工的调用构造函数 进行对象初始化 t3.print(); system("pause"); } |
构造函数用来完成对象的构造(初始化)工作,
赋值构造函数(copy构造函数) 和 = 操作是两个不同的概念
赋值构造函数(copy构造函数)的四个应用场景
void main81() { Test88 t1; //t1.SetBuf("我是t1"); t1.setA(10); Test88 t3; //第一种场景 //1赋值构造函数和=操作是两个不同的概念 //2 赋值构造函数 copy构造函数 也是构造函数 //在这个场景之下。t2被创建,并且自动的调用copy构造 //3 当我们没有编写copy构造函数(赋值构造函数)的时候,c++编译器会默认给我们提供一个copy构造函数 执行的是浅copy Test88 t2 = t1; //对象t2的初始化 cout<<t2.getA()<<endl; //t2 = t1; //是对象的=操作 system("pasue"); } |
void main888() { Test88 t1; t1.setA(10); //第二种场景 Test88 t2(t1); system("pasue"); } |
void f ( Location p ) { cout << "Funtion:" << p.GetX() << "," << p.GetY() << endl ; } void playobjmain() { Location A ( 1, 2 ) ; f ( A ) ; } |
class Location { public: Location( int xx = 0 , int yy = 0 ) { X = xx ; Y = yy ; cout << "Constructor Object.\n" ; } Location( const Location & p ) //复制构造函数 { X = p.X ; Y = p.Y ; cout << "Copy_constructor called." << endl ; } ~Location() { cout << X << "," << Y << " Object destroyed." << endl ; } int GetX () { return X ; } int GetY () { return Y ; } private : int X , Y ; } ; void f ( Location p ) { cout << "Funtion:" << p.GetX() << "," << p.GetY() << endl ; } // void playobjmain() // { // Location A ( 1, 2 ) ; // f ( A ) ; // } Location g() { Location A(1, 2); return A; } void main101() { Location B; B = g(); } void main102() { //g() 返回一个匿名对象 Location B = g(); } void main1111() { main102(); system("pause"); } |
构造函数析构函数调用规则
规则总结: /* 1 当类中没有定义任何一个构造函数时,c++编译器会提供无参构造函数和拷贝构造函数 2 当类中定义了任意的非拷贝构造函数(无参、有参),c++编译器不会提供无参构造函数 3 当类中定义了拷贝构造函数时,c++编译器不会提供无参数构造函数 4 默认拷贝构造函数成员变量简单赋值 总结:只要你写了构造函数,那么你必须用。 */ |
//对象做函数参数 //1 研究拷贝构造 //2 研究构造函数,析构函数的调用顺序 //总结 构造和析构的调用顺序 #include "iostream" using namespace std; class ABCD { public: ABCD(int a, int b, int c) { this->a = a; this->b = b; this->c = c; printf("ABCD() construct, a:%d,b:%d,c:%d \n", this->a, this->b, this->c); } ~ABCD() { printf("~ABCD() construct,a:%d,b:%d,c:%d \n", this->a, this->b, this->c); } int getA() { return this->a; } protected: private: int a; int b; int c; }; class MyE { public: MyE():abcd1(1,2,3),abcd2(4,5,6),m(100) { cout<<"MyD()"<<endl; } ~MyE() { cout<<"~MyD()"<<endl; } MyE(const MyE & obj):abcd1(7,8,9),abcd2(10,11,12),m(100) { printf("MyD(const MyD & obj)\n"); } protected: //private: public: ABCD abcd1; //c++编译器不知道如何构造abc1 ABCD abcd2; const int m; }; int doThing(MyE mye1) { printf("doThing() mye1.abc1.a:%d \n", mye1.abcd1.getA()); return 0; } int run2() { MyE myE; doThing(myE); return 0; } // int run3() { printf("run3 start..\n"); ABCD abcd = ABCD(100, 200, 300); //若直接调用构造函数哪 //想调用构造函数对abc对象进行再复制,可以吗? //在构造函数里面调用另外一个构造函数,会有什么结果? //ABCD(400, 500, 600); //临时对象的生命周期 printf("run3 end\n"); return 0; } int main() { //run2(); run3(); system("pause"); return 0; } |
深拷贝浅拷贝
name( name &obj) { cout <<" copy Constructing " << endl ; char *pn2 = obj.getPn(); pname = (char *)malloc(strlen(pn2) +1); if (pname!=NULL) strcpy(pname,pn2) ; //pname = new char[strlen(pn)+1] ; //if (pname!=0) strcpy(pname,pn) ; size = strlen(pn2) ; } |
static专题讲座
void main1888() { ///GetStatic(); //GetStatic(); Test3 t1(1, 3), t2(3, 4), t3(5, 65); //Test(&t2, 3, 4), cout<<Test3::getCount()<<endl;; cout<<t3.getCount()<<endl;; system("pause"); } |
重载=操作符内存泄露场景
void operator=( name &obj1) { cout <<" 执行=操作" << endl ; if (pname != NULL) { free(pname); pname = NULL; size = 0; } char *pn = obj1.getPn(); pname = (char *)malloc(strlen(pn) +1); if (pname!=NULL) strcpy(pname,pn) ; //pname = new char[strlen(pn)+1] ; //if (pname!=0) strcpy(pname,pn) ; pname[0] = ‘m‘; size = strlen(pn) ; } |