C++ 拷贝构造函数的在继承中的总结

目录

  • 拷贝构造函数字面意思
  • 拷贝构造函数基本格式:
  • 下面代码证明不写拷贝构造函数,系统自动生成拷贝构造函数
  • 子类继承父类的时候拷贝构造函数时,如果成员变量没有默认值,必须在初始化列表中把父类的构造函数初始化
  • 父类中的成员变量都有默认值,子类的拷贝构造函数不需要调用父类的构造函数

拷贝构造函数字面意思

拷贝构造函数,基本意思就是,用一个对象,初始化另外一个对象调用的函数,就是拷贝构造函数.只有对象被创建的时候才会调用,用已经存在的对象赋值给另一个对象的时候不会调用拷贝构造函数.

拷贝构造函数基本格式:

基本格式是:构造函数传入的参数是一个对象的引用,后面冒号是构造函数的初始化列表,用传入对象的成员变量初始化本对象的成员变量
下面代码做例子:

class Person{
public:
    int m_age;
    Person(){}//默认构造函数
    
    //基本格式是:构造函数传入的参数是一个对象的引用,后面冒号是构造函数的初始化列表,用传入对象的成员变量初始化本对象的成员变量
    Person(Person& person):m_age(person.m_age){//构造函数参数是一个对象的引用
        cout<<"调用自己写的拷贝构造函数"<<endl;
    }
};
int main(int argc, const char * argv[]) {
    Person p1;
    p1.m_age = 10;
    Person p2(p1); //不写拷贝构造函数,默认也有拷贝构造函数,所以用可以用p1来初始化p2,并且打印"调用自己写的拷贝构造函数"
    
    cout <<&p1 <<endl<< &p2  <<endl<< p2.m_age <<endl;
    /*
     打印结果p1,p2的地址不同,但是p2的m_age也是10,说明拷贝构造函数成功
     0x30412b388
     0x30412b380
     10
     Pro
     */
}

下面代码证明不写拷贝构造函数,系统自动生成拷贝构造函数

class Person{
public:
    int m_age;
    Person(int age):m_age(age){
        cout<<"自己写的普通构造函数"<<endl;
    }
};
 //不写拷贝构造函数,默认系统自动生成
int main(int argc, const char * argv[]) {
    Person p1(10);
    Person p2(p1); //不写拷贝构造函数,默认也有拷贝构造函数,所以用可以用p1来初始化p2,里面执行的操作就是把所有成员变量进行赋值
    cout << p2.m_age <<endl;
}

子类继承父类的时候拷贝构造函数时,如果成员变量没有默认值,必须在初始化列表中把父类的构造函数初始化

这段话有点绕,简单理解就是,因为调用拷贝构造函数的时候每个成员变量都要有明确的值,所以如果父类的成员变量没有默认值,就得在拷贝构造函数的初始化列表里面初始化父类的构造函数,否则编译报错,看下面代码例子:


class Person{
public:
    int m_age;
    Person(int age):m_age(age){
        cout<<"Person(int age)默认构造函数执行"<<endl;
    }
    Person(Person &person):m_age(person.m_age){ //自己写的拷贝构造函数,覆盖系统默认的拷贝构造函数
        cout<<"(Person &p1):m_age(p1.m_age)"<<endl;
    }
};

class Student:public Person{
public:
    char* m_name;
    Student(int age ,char* name):Person(age) ,m_name(name){//默认构造函数
    //因为不能写 m_age(age),编译报错,因为父类Person还没有初始化,所以不存在m_age,所以在初始化列表里面调用父类的Perosn(age)类初始化m_age
    }
    Student(Student& student):Person(student.m_age),m_name(student.m_name){//父类Person因为有m_age成员变量没有默认值,所以必须调用父类的构造函数,否则编译会报错:没有明确调用父类的构造函数,这里用传进来的引用对象的m_age调用父类的 Person(int age)来初始化
    }

};
int main(int argc, const char * argv[]) {
    Student s1(11,"zhang san");
    Student s2(s1);
    cout << s2.m_age <<endl << s2.m_name <<endl;
}

父类中的成员变量都有默认值,子类的拷贝构造函数不需要调用父类的构造函数

看下面代码,因为父类Person(int age = 0)有默认值,所以不用给m_age赋值,但是这样靠背,拷贝的对象父类的成员变量只会被赋值成默认值

//父类中的成员变量都有默认值,子类的拷贝构造函数不需要调用父类的构造函数
class Person{
public:
    int m_age;
    Person(int age = 0):m_age(age){
        cout<<"Person(int age)默认构造函数执行"<<endl;
    }
    Person(Person &p1):m_age(p1.m_age){ //自己写的拷贝构造函数,覆盖系统默认的拷贝构造函数
        cout<<"(Person &p1):m_age(p1.m_age)"<<endl;
    }
};

class Student:public Person{
public:
    char* m_name;
    Student(int age ,char* name):m_name(name){//因为父类Person(int age = 0)有默认值,所以不用给m_age赋值,但是这样靠背,拷贝的对象父类的成员变量只会被赋值成默认值
    }
    Student(Student& s1):m_name(s1.m_name){
        
    }
};
int main(int argc, const char * argv[]) {
    Student s1(11,"zhang san");//传入的11,没有被使用,而是调用了父类的Person(int age = 0) ,所以结果是0,zhangsan
    cout << s1.m_age <<endl << s1.m_name <<endl;
    
    Student s2(s1);
    cout << s2.m_age <<endl << s2.m_name <<endl;
}

你可能感兴趣的:(c++,c++,拷贝构造,拷贝构造函数,继承,初始化)