C++ 构造函数,析构函数,拷贝构造函数

来源:互联网 发布:脸上红血丝 知乎 编辑:程序博客网 时间:2024/05/17 23:44

1 C++类的普遍写法
新建NBAPlayer.cpp文件

#include "NBAPlayer.h"void NBAPlayer::setAge(int age){    this->age = age;}int NBAPlayer::getAge(){    return this->age;}void NBAPlayer::setName(char *name){    this->name = name;}char* NBAPlayer::getName(){    return this->name;}

新建NBAPlayer.h文件

#pragma onceclass NBAPlayer{public:    int age;    char *name;public:    void setAge(int age);    int getAge();    void setName(char *name);    char *getName();};

调用

#include "NBAPlayer.h"void main(){    NBAPlayer n1;    n1.name = "WestBrook";    n1.age = 28;    cout << n1.getName() <<endl;    system("pause");}

打印结果

WestBrook

2 构造函数
对象初始化时调用

class NBAPlayer{private:    char *name;    int age;public:    //无参构造函数(会覆盖默认的午餐构造函数)    NBAPlayer(){        cout << "无参构造函数" << endl;    }    //有参构造函数会覆盖默认的构造函数    NBAPlayer(char *name,int age){        this->name = name;        this->age = age;        cout << "有参构造函数"<<endl;    }};
void main(){    NBAPlayer n;    system("pause");}

打印结果

无参构造函数

当调用有参数构造时:

void main(){    NBAPlayer n2("Durrant",28);    system("pause");}

打印结果

有参构造函数

另外一种调用方式

NBAPlayer n3 = NBAPlayer("Stephen Curry",29);

3 拷贝构造函数
对象销毁时调用

class NBAPlayer{private:    char *name;    int age;public:    NBAPlayer(){        this -> name = (char*)malloc(100);        strcpy(name,"Rose");        age = 30;        cout << "无参构造函数" << endl;    }    //析构函数    //当对象要被系统释放时,析构函数被调用    ~NBAPlayer(){        cout << "析构" << endl;        //释放内存        free(this->name);    }};void func(){    NBAPlayer n;}
void main(){    func();    system("pause");}

打印结果

无参构造函数析构

4 拷贝构造函数

class NBAPlayer{private:    char *name;    int age;public:    NBAPlayer(char*name,int age){        this->name = name;        this->age = age;        cout << "有参构造函数" << endl;    }    //拷贝函数    //默认拷贝构造函数,是值拷贝    NBAPlayer(const NBAPlayer &obj){        this->name=obj.name;        this->age = obj.age;        cout << "拷贝构造函数" << endl;    }    void myPrint(){        cout << name << "," << age << endl;    }};

1 声明时赋值

void main(){    NBAPlayer n("Derric Rose",29);    //拷贝构造函数被调用的场景    //1 声明时赋值    NBAPlayer n1 = n;    n1.myPrint();    system("pause");}

打印结果

有参构造函数拷贝构造函数Derric Rose,29

2 作为参数传入方法

void func(NBAPlayer n){    n.myPrint();}
void main(){    NBAPlayer n("Derric Rose",29);    //2 作为参数传入 实参给形参赋值    func(n);    system("pause");}

打印结果

有参构造函数拷贝构造函数Derric Rose,29

3 作为参数返回值返回,给变量初始化赋值

NBAPlayer func1(NBAPlayer n){    n.myPrint();    return n;}void main(){    NBAPlayer n("Derric Rose",29);    //3 作为参数返回值返回,给变量初始化赋值    NBAPlayer n2 = func1(n);    system("pause");}

打印结果

有参构造函数拷贝构造函数Derric Rose,29拷贝构造函数

可以看出最后一个拷贝函数执行是返回值给变量赋值时调用的。
总而言之,拷贝函数在变量初始化赋值时将会被调用。2,3中拷贝函数是在1的基础上衍生出来的。归根结底还是变量在初始化赋值时调用拷贝函数。

4 不会调用拷贝函数的情况

void main(){    NBAPlayer n("Derric Rose",29);    NBAPlayer n2("Wade",30);    //这种情况 不会调用拷贝函数    n2 = n;    system("pause");}

5 浅拷贝

class NBAPlayer{private:    char *name;    int age;public:    NBAPlayer(char*name, int age){        this->name = (char*)malloc(100);        strcpy(this->name,name);        this->age = age;        cout << "有参构造函数" << endl;    }    NBAPlayer(const NBAPlayer &obj){        this->name = obj.name;        this->age = obj.age;        cout << "拷贝构造函数" << endl;    }    ~NBAPlayer(){        cout << "析构函数"<< endl;        free(this->name);    }    void myPrint(){        cout << name << "," << age << endl;    }};void func(){    NBAPlayer n1("McGready",38);    NBAPlayer n2 = n1;    n2.myPrint();}
void main(){    func();    system("pause");}

运行后将会打印

有参构造函数拷贝构造函数McGready,38析构函数析构函数

然后程序会崩溃,因为在n1调用析构函数释放name后,n2在调用析构函数时,name将会为空。也就是说n1和n2操作的是同一个对象。

6 深拷贝
其他代码一样 只是在拷贝函数中把属性的值拷贝了一份

NBAPlayer(const NBAPlayer &obj){        int len = strlen(obj.name);        this->name = (char*)malloc(len+1);        //拷贝属性值        strcpy(this->name,obj.name);        this ->age = obj.age;        cout << "拷贝构造函数" << endl;    }

在此执行,运行结果一样,但是将不会报错。