C++在继承的构造函数和析构函数

来源:互联网 发布:浙江盛和网络金锋 编辑:程序博客网 时间:2024/05/16 06:44
1. 在继承中,基类的构造函数构建对象的基类部分,派生类的构造函数构建对象的派生类部分。
2. 当创建派生类对象时 先用派生类的构造函数调用基类的构造函数构建基类 ,然后再执行派生类构造函数构造派生类。
即先构造基类再构造派生类的顺序。执行析构函数的顺序与此相反。
3. 调用基类带参数的构造函数的方法:在派生类的构造函数中使用初始化列表的形式就可以调用基类带参数的构造函
数初始化基类成员,如B():A(int i){},类B是类A的派生类。
4. 派生类的构造函数调用基类的构造函数的方法为 :
4.1   如果派生类没有 显示用初始化列表调用基类的构造函数时 ,这时就会用派生类的 构 造函数调用基类的默认构造
函数,构造完基类后,才会执行派生类的构造函数函数体,以保证先执行基类构造函数再执行派生类构造函数
的顺序,如果基类没有默认构造函数就会出错 。
4.2   如果派生类用显示的初始化列表调用基类的构造函数时 ,这时就会检测派生类的初始化列表,当检测到显示调
用基类的构造函数时,就调用基类的构造函数构造基类 ,然后再构造派生类,以保证先执行基类构造函数再执
行派生类构造函数的顺序,如果基类没有定义派生类 构造函数初始化列表调用的构造函数版本就会出错 。
6. 如果在基类中没有定义 默认构造函数 ,但定义了其 他构造函数版本,这时派生类中定义了 几个构造函数的
不同版本 ,
这时只要派生类有一个 构造函数没有显示调用基类中定义的构造函数版本就会发生错误 ,因为编译器会首先检查
派生类构造函数调用基类构造函数的匹配情况,如果发现不匹配就会出错,即使没有创建任何类的对象都会出错 ,
而不管这个派生类的对象有没有调用派生类的这个 构造函数 。比如:基类有一个构造函数版本A(int i)而没有定义
默认构造函数,派生类B,有这几个版本的构造函数B():A(4){},B(int  i):A(5){},再有语句B(int  i,  int  j){}

没有显示调用
基类定义的构造函数而是调用基类的默认构造函数 ,如果创建了B m和语句B m(1)时都会提示没有可用的基类默认
构造函数可用的错误,虽然这时类B的对象m没有调用派生类B的带有两个形参的构造函数,但同样会出错。
7. 同样的道理,如果基类中定义了 默认构造函数 ,却没有其他版本的构造函数,而这时派生类却显示调用了基
类构造函数的其他版本,这时就会出错,不管你有没有创建类的对象,因为编译器会先在创建对象前就检查构造函数的匹
配问题。
8. 派生类只能初始化他的直接基类 。比如类C是类B的子类,而类B又是类A的子类,这时class  C:public  B
{public:
B():A(){} };将会出错,该语句试图显示调用类B的基类类A的构造函数,这时会出现类A不是类C的基类的错误。
9. 继承中的复制构造函数和构造函数一样,基类的复制构造函数复制基类部分,派生类的复制构造函数复制派生

类部分。
10.派生类复制构造函数调用基类复制构造函数的方法为:A(const A& m):B(m){}其中B是基类,A是派生类。
11.如果在派生类中定义了 复制构造函数而没有用初始化列表显示调用基类的复制构造函数 ,这时不管基类是
否定义了复制构造函数,这时出现派生类对象的复制初始化情况时就将调用基类中的默认构造函数初始化基类的成员变量,注意是默认构造函数不是默认复制构造函数,如果基类没有默认构造函数就会出错 。也就是说派生类的 复制构造
函数的默认隐藏形式是B(const B&  j):A(){}这里B是A的派生类,也就是说如果不 显示用初始化列表形式调用基类
的复制构告函数时,默认情况下是用初始化列表的形式调用的是基类的默认构造函数。
12.当在派生类中定义了 复制构造函数且显示调用了基类的复制构造函数 ,而基类却没有定义基类的复制构造函
数时,这时出现派生类对象的复制初始化情况就将调用基类中的默认复制构造函数初始化基类部分,调用派生类的复制构
造函数初始化派生类部分,因为复制构造函数只有一种形式,即A(const  A& m){},比如当出现调用时A(const  
A& m):B(m){}如果这时基类B没有定义复制构造函数,则该语句将会调用派生类A的默认复制构造函数。
12.如果基类定义了 复制构造函数 ,而派生类没有定义时,则会调用基类的 复制构造函数初始化基类部分 ,调
用派生类的默认复制构造函数初始化派生类部分。

例:基类不定义默认构造函数,派生类不定义复制构造函数而基类定义复制构造函数的情形。
class A
{
    public:
    int a,a1;
    A(int i){
        a=a1=11;
        cout<<"构造A1"<<endl;
    }
    A(const A& J){
        a=4;
        a1=4;
        cout<<"复制构造函数"<<endl;
    }
    ~A(){
        cout<<"析构"<<endl;
    }
};
//类B不定义复制构造函数
class B:public A
{
    public:
    int b,b1;
    //B(){b=b1=2;cout<<"构造B"<<endl;}  //错误,此语句会调用基类中的默认构造函数,而基类没有默认

构造函数。
    //B(int i,intj){b=b1=3;}//错误,同上,此语句没有显示调用基类构造函数,就会调用基类的默认构造

函数,而这时基类没有默认构造函数。
    B(int i):A(2){
        b=b1=3;
        cout<<"构造B1"<<endl;
    }//显示调用基类带一个形参的构造函数,注意语法
    ~B(){
        cout<<"析构B"<<endl;
    }
};
int main(){
    B m(0);
    cout<<m.a<<m.b<<endl;
    B m1(m);
    cout<<m1.a<<m1.b<<endl; //输出43,注意,此语句将调用基类定义的复制构造函数,然后调用派生类的

默认复制构造函数。
    return 0;
}

例:派生类B使用默认的B(const B& K):A(){}形式,而不使用初始化列表显示调用基类A中的复制构造函
数的情况
class A
{
    public:
    int a,a1;
    A(){
        a=a1=2;
        cout<<"构造A"<<endl;
    }
    A(int i){
        a=a1=11;
        cout<<"构造A1"<<endl;
    }
    A(const A& J){
        a=4;
        a1=4;
        cout<<"A复制构造函数"<<endl;
    }
    ~A(){
        cout<<"析构"<<endl;
    }
};
//类B不定义复制构造函数
class B:public A
{
    public:
    int b,b1;
    B(){
        b=b1=2;
        cout<<"构造B"<<endl;
    }
    //B(int i,int j):A(4,4){} //Fcc错误,调用了基类没有定义的带两个参数的构造函数。
    B(int i):A(2){
        b=b1=3;
        cout<<"构造B1"<<endl;
    }//显示调用基类带一个形参的构造函数,注意语法
       B(const B& K){
        b=b1=5;
        cout<<"B复制构造函数"<<endl;
    } //注意,这里没有显示调用基类的复制构造函数,而是用默认的B(const B& k):A(){}的
//形式调用的基类中的默认构造函数,注意是默认构造函数而不是默认复制构造函数。
    ~B(){
        cout<<"析构B"<<endl;
    }
};
int main(){
    B m(0);
    cout<<m.a<<m.b<<endl;
    B m1(m);
    cout<<m1.a<<m1.b<<endl;
    //输出 25,注意此语句将调用基类的默认构造函数将基类中的成员初始化为,再调用派生类的复制构造

函数将类B中的成员b初始化
    return 0;
}


原创粉丝点击