c++ --> 父类与子类间的继承关系

一、父类与子类

父类与子类的相互转换

1、派生类的对象可以赋给基类,反之不行

2、基类的指针可以指向派生类,反之不行

3、基类的引用可以初始化为派生类的对象,反之不行

4、派生类指针必须强制转换为基类指针后才可以指向基类

5、基类指针转换为派生类指针容易导致崩溃性错误

6、虚基类的引用或派生不能转换为派生类
 
class father{
  //
};
class son : public father{
  //
};
int main() { father f; son s; f = s;//正确 s = f;//错误 father *pf = new son;//正确 son *ps = new father;//错误 father &rf = s;//正确 father &rs = f;//错误 return 0; }

 

继承关系对基类成员的影响

  公有成员 保护成员 私有成员
公有继承 公有 保护 不可访问
保护继承 保护 保护 不可访问
私有继承 私有 私有 不可访问
成员函数 1 1 1
对象 1 0 0
子类 1 1 0

1:可以访问 0:不可访问

当所有成员都变成不可访问时,再往下派生就没有意义了
 
 
 
 
二、子类的构造与析构
1、构造派生类对象时,先执行基类的构造函数,再执行子类的构造函数,析构反之
class father
{
public:
    father(){cout<<"father construct"<<endl;}
    ~father(){cout<<"father delete"<<endl;}
};
class son : public father
{
public:
    son(){cout<<"son construct"<<endl;}
    ~son(){cout<<"son delete"<<endl;}
};
int main()
{
    son s;
    return 0;
}

输出:

father construct
son construct
son delete
father delete

 

2.如果是多重继承,基类的构造顺序按给定的顺序,析构反之

class father
{
public:
    father(){cout<<"father construct"<<endl;}
    ~father(){cout<<"father delete"<<endl;}
};
class mother
{
public:
    mother(){cout<<"mother construct"<<endl;}
    ~mother(){cout<<"mother delete"<<endl;}
};
class son : public father, public mother
{
public:
    son(){cout<<"son construct"<<endl;}
    ~son(){cout<<"son delete"<<endl;}
};
int main()
{
    son s;
    return 0;
}

输出:

father construct
mother construct
son construct
son delete
mother delete
father delete

 

3.利用基类的构造函数构造子类,效率更高

class father
{
    int x;
public:
    father(int a):x(a){cout<<"father construct:"<<x<<endl;}
};
class son : public father
{
    int y;
public:
    son(int a, int b):father(a), y(b){cout<<"son construct:"<<y<<endl;}
};
int main()
{
    son s(1, 2);
    return 0;
}

输出:

father construct:1
son construct:2

 

 

三、多重继承

1.多重继续的二义性,根本原因是

技术分享

假如A有Test(),则B和C都有Test(),于是D产生了二义性

class A
{
public:
    void Test(){cout<<"A"<<endl;}
};
class B
{
public:
    void Test(){cout<<"B"<<endl;}
};
class C : public A, public B
{
};
int main()
{
    C c;           
    c.Test();      //错误
    c.A::Test();   //正确,输出:A
    c.B::Test();   //正确,输出:B
    return 0;
}

 

2.编译器通常都是从离自己最近的目录树向上搜索的

子类的Test()覆盖了基类的Test(),并不代表基类的Test()消失,只是不能直接访问

class A
{
public:
    void Test(){cout<<"A"<<endl;}
};
class B
{
public:
    void Test(){cout<<"B"<<endl;}
};
class C : public A, public B
{
    void Test(){cout<<"C"<<endl;}
};
int main()
{
    C c;           
    c.Test();      //正确,输出:C
    c.A::Test();   //正确,输出:A
    c.B::Test();   //正确,输出:B
    return 0;
}

 

3.对于单一继承,子类能否访问父类的父类,只与继承的方式有关

对于多重继承,子类不能直接访问父类的父类。
 

4.用virtual来避免二义性。

class B : virtual public A.

 

 

四、继承与包含

1.一个类的成员变量列表中包含另一个类的对象,叫做包含(包容)。

2.包含与私有继承的区别:

包含:

1)使程序看上去更清晰易懂

2)不存在继承带来的问题

3)可以包括另一个类的多个对象

 

私有继承:

1)可以访问基类的保护成员

2)可以重定义虚函数,实现多态

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。