C++ 对象间的继承关系(赋值兼容规则)

目录

一、三种继承方式:

二、单继承:一个派生类只有一个直接基类的情况

 三、多层继承

四、多继承:由多个基类共同派生出新的派生类

五、菱形继承:不同的类在继承关系中会产生一个环

六、赋值兼容规则

1. 派生类的对象可以赋值给基类对象

 

2. 派生类的对象可以初始化基类的引用

3.派生类对象的地址可以赋给指向基类的指针

4.赋值兼容的易错点: 

 七、成员对象和继承的区别

1.以私有继承和私有成员为例:

2. 构建顺序:先从左到右,后从上到下

3.销毁顺序:和构建顺序相反  


 相关概念

C++ 通过类派生 的机制来支持继承。被继承的类称为基类   ,新产生的类为派生类 或子类,基类和派生类的集合 称作类继承层次结构。

由基类派生出派生类,其设计形式为: 

class 派生类名 访问限定符 基类名

{ private:       成员表1; //派生类增加或替代的私有成员

          public:       成员表2; //派生类增加或替代的公有成员

          protected:        成员表3; //派生类增加或替代的保护成员

};//分号不可少

 如:

 在继承关系中,派生类会继承基类的全部数据成员,除了构造函数和析构函数不能继承;这是因为:我们所创建派生类的对象,虽然和基类的对象有相同之处,但是仍然是不同的对象。所以,适 用于基类的构造函数和析构函数不可能完全满足派生类对象的创建和消亡的善后工作。因此,构造函数 和析构函数不被继承

一、三种继承方式:

1.公有继承 public:

基类的公有成员在派生类中仍为公有,基类的保护成员在派生类中仍为保护 ,基类的私有成员被继承后,不允许在派生类中访问。

2.保护继承 protected:

基类的公有成员在派生类中变为保护,基类的保护成员在派生类中仍为保护 ,基类的私有成员被继承后,不允许在派生类中访问。

3.私有继承 private:

基类的公有成员在派生类中变为私有,基类的保护成员在派生类中变为私有 ,基类的私有成员被继承后,不允许在派生类中访问。

 

 不论哪种继承,基类的私有成员都会被继承,但是不允许派生类之类访问基类的私有成员

二、单继承:一个派生类只有一个直接基类的情况

例:

class Object

{

private:   int  a;

public:    int  c;

};

class Base : public Object  //只继承一个基类

{

private:   int  x;

public:    int   z;

};

int main() {    

Object obj;    

Base base;

   return 0;

}

 派生类base 会继承基类 obj 的所有数据成员,如下图:派生类会先创建一个不具名基类对象,并用基类名Object 进行标识。

 三、多层继承

class Object

{

private:   int  a;

public:    int  c;

};

class Base : public Object 

{

private:   int  x;

public:    int   z;

};

class Test : public Base

{
private:

int value;

}

int main() {    

Object obj;

Base base;

Test test;

   return 0;

}

多层继承关系中,构建 tes t对象时,会先构建其父类,然后在构建 test;

按照图示顺序进行构建:

四、多继承:由多个基类共同派生出新的派生类

class Object

{

private:   int  a;

};

class Base : 

{

public:    int   z;

};

class Test :public Object ,  public Base //由多个父类派生

{
private:

int value;

}

int main() {    

  Test test;

   return 0;

}

 如图:

五、菱形继承:不同的类在继承关系中会产生一个环

如图:

class Base
{
private:
    int val=7;

public:

    string w="hello";
 };
class Test1 : public Base
{
private:
    int x=0;
};
class Test2 : public Base
{
private:
    int y=1;
};
class Bing : public Test1,public Test2
{
private:
    int z=2;
};

int main()
{
    Bing s1;

    return 0;
}

创建顺序如下图: 

 打来监视器如下图:

 我们发现 s1对象中由两个 Base 类,他们的数据成员内容相同,如果想通过s1对象访问Base中的公有数据成员w,必须明确指出其类名

如图:

而,作为设计人员,我们不想让Base被s1 对象继承多次(重复的数据且内存开销大),而只被继承一次,有两种解决方法:

 1.虚基类  

2.避开这种菱形继承

六、赋值兼容规则

                                             大前提:公有继承;

  • 派生类的对象可以赋值给基类对象。 
  • 派生类的对象可以初始化基类的引用。 
  • 派生类对象的地址可以赋给指向基类的指针。

例:

class Base
{
private:
    int val=7;
public:
    string w = "hello";
 };
class Test : public Base
{
private:
    int x=0;

public:

    int root=11;
};

int main()

{
  Test test;

  Base base;

  base = test;       //派生类的对象可以赋值给基类对象。

Base *p = &test;  //派生类对象的地址可以赋给指向基类的指针。

Base& b = test;  //派生类的对象可以初始化基类的引用。 

return 0;

}

1. 派生类的对象可以赋值给基类对象

派生类的数据成员个数始终>=基类数据成员个数,在赋值时会产生截断,只将公共部分进行赋值,类似于这样

2. 派生类的对象可以初始化基类的引用

 b 是派生类 test 的别名,由于 b的类型为Base基类,所以 通过 b 只能访问Base基类中的数据成员,不可以访问派生类中新增的数据成员。

如图:

3.派生类对象的地址可以赋给指向基类的指针

 p指向test的首地址,由于p的类型是基类指针,所以只能访问基类Base的数据成员。

4.赋值兼容的易错点: 

class object 
{
    int value;
public:
    object(int x = 0) :  value(x) {
        cout << "Creat object " << endl;
    }
    ~object()
    {
        cout << "Destory object " << endl;
    }
};
class base : public object
{
    int xval;
public:
    base(int x = 10) :object(x), xval(10) {
        cout << "Creat base" << endl;
    }
    ~base()
    {
        cout << "Destory base" << endl;
    }
}; 

当我们用new运算符申请派生类对象并将他赋给基类指针,调用delete 回收空间时,会发现只调用了基类的析构函数,并没有调用派生类的析构函数,就会出现内存泄漏问题。

此时,需要将p强转为派生类指针,即可避免内存泄漏。

  

 七、成员对象和继承的区别

1.以私有继承和私有成员为例:

class Base{
private:
    int val = 7;
protected:
    int op = 2;
public:
    string w = "hello"; 
};
class Test : private Base{
private:
    int x = 0;
    Base ba;
public:
    int root=11;
    void setval()
    {    
        Base::w = "world";
        ba.w = "newdata";
        ba.op = 12;        //error  不可访问保护成员
        Base::op = 16;     //可以访问保护成员
        ba.val = 12;       //error  不可访问私有数据成员
        Base::val = 12;    //error  不可访问私有数据成员

        x = 13;
    }
};

int main()

{
  Test test;

  return 0;

}

保护继承和保护成员,公有继承和公有成员类似。 

即:当前类的成员对象的保护属性在当前类中不可访问  

2. 构建顺序:先从左到右,后从上到下

3.销毁顺序:和构建顺序相反  

  • 3
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
鸡啄米的资料,大家可以上官网看。这是我整理的压缩包,大家可以离线看。(这个资源还要大家积分,实在是惭愧,只因积分不够用,抱歉,体谅!) 大家要是觉得不错,可以下载我整理得另一套资源:VS2010+MFC编程入门,也是鸡啄米的,写得不错,通俗易懂! --------------------------完整目录如下------------------- 第一部分:C++编程概述 鸡啄米:C++编程入门系列之前言 鸡啄米:C++编程入门系列之一(进制数) 鸡啄米:C++编程入门系列之二(原码、反码与补码) 第二部分:C++简单程序设计 鸡啄米:C++编程入门系列之三(VS2010的使用介绍) 鸡啄米:C++编程入门系列之四(数据类型) 鸡啄米:C++编程入门系列之五(运算符和表达式) 鸡啄米:C++编程入门系列之六(算法的基本控制结构之选择结构) 鸡啄米:C++编程入门系列之七(算法的基本控制结构之循环结构) 鸡啄米:C++编程入门系列之八(自定义数据类型) 第三部分:函数 鸡啄米:C++编程入门系列之九(函数的定义与调用) 鸡啄米:C++编程入门系列之十(函数的参数传递与内联函数) 鸡啄米:C++编程入门系列之十一(重载函数与函数模板) 第四部分:类与对象 鸡啄米:C++编程入门系列之十二(类与对象:面向对象设计的基本思 想和特点) 鸡啄米:C++编程入门系列之十三(类与对象:类的声明、成员的访问 控制和对象) 鸡啄米:C++编程入门系列之十四(类与对象:构造函数和析构函数) 鸡啄米:C++编程入门系列之十五(类与对象:类的组合) 鸡啄米:C++编程入门系列之十六(类与对象:类模板) 鸡啄米:C++编程入门系列之十七(类与对象:UML简介) 第五部分:C++程序设计必知 鸡啄米:C++编程入门系列之十八(C++程序设计必知:作用域和可见 性) 鸡啄米:C++编程入门系列之十九(C++程序设计必知:生存期) 鸡啄米:C++编程入门系列之二十(C++程序设计必知:数据和函数) 鸡啄米:C++编程入门系列之二十一(C++程序设计必知:类的静态成 员) 鸡啄米:C++编程入门系列之二十二(C++程序设计必知:友元) 鸡啄米:C++编程入门系列之二十三(C++程序设计必知:常引用、常对 象和对象的常成员) 鸡啄米:C++编程入门系列之二十四(C++程序设计必知:多文件结构和 编译预处理命令) 第六部分:数组、指针和字符串 鸡啄米:C++编程入门系列之二十五(数组、指针和字符串:数组的声 明和使用) 鸡啄米:C++编程入门系列之二十六(数组、指针和字符串:数组的存 储与初始化、对象数组、数组作为函数参数) 鸡啄米:C++编程入门系列之二十七(数组、指针和字符串:指针变量 的声明、地址相关运算--“*”和“&”) 鸡啄米:C++编程入门系列之二十八(数组、指针和字符串:指针的赋 值和指针运算) 鸡啄米:C++编程入门系列之二十九(数组、指针和字符串:指向数组 元素的指针和指针数组) 鸡啄米:C++编程入门系列之三十(数组、指针和字符串:指针用作函 数参数、指针型函数和函数指针) 鸡啄米:C++编程入门系列之三十一(数组、指针和字符串:对象指 针) 鸡啄米:C++编程入门系列之三十二(数组、指针和字符串:动态内存 分配和释放) 鸡啄米:C++编程入门系列之三十三(数组、指针和字符串:用字符数 组存放和处理字符串) 鸡啄米:C++编程入门系列之三十四(数组、指针和字符串:string 类) 第七部分:继承与派生 鸡啄米:C++编程入门系列之三十五(继承与派生:概念介绍与派生类 的声明) 鸡啄米:C++编程入门系列之三十六(继承与派生:派生类从基类继承 的过程) 鸡啄米:C++编程入门系列之三十七(继承与派生:派生类对基类成员 的访问控制之公有继承) 鸡啄米:C++编程入门系列之三十八(继承与派生:派生类对基类成员 的访问控制之保护继承与私有继承) 鸡啄米:C++编程入门系列之三十九(继承与派生:派生类的构造函 数) 鸡啄米:C++编程入门系列之四十(继承与派生:派生类的析构函数) 鸡啄米:C++编程入门系列之四十一(继承与派生:作用域分辨符) 鸡啄米:C++编程入门系列之四十二(继承与派生:虚基类及其派生类 的构造函数) 鸡啄米:C++编程入门系列之四十三(继承与派生:赋值兼容规则) 第八部分:多态性 鸡啄米:C++编程入门系列之四十四(多态性:多态的概念和类型) 鸡啄米:C++编程入门系列之四十五(多态性:运算符重载的概念和规 则) 鸡啄米:C++编程入门系列之四十六(多态性:运算符重载为类的成员 函数) 鸡啄米:C++编程入门系列之四十七(多态性:运算符重载为类的友元 函数) 鸡啄米:C++编程入门系列之四十八(多态性:虚函数) 鸡啄米:C++编程入门系列之四十九(多态性:纯虚函数和抽象类) 第九部分:异常处理 鸡啄米:C++编程入门系列之五十(异常处理) 鸡啄米:C++编程入门系列之目录和总结

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值