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

目录

一、三种继承方式:

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

 三、多层继承

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

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

六、赋值兼容规则

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

 

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

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

4.赋值兼容的易错点: 

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

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

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

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


 相关概念

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

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

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

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

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

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

};//分号不可少

 如:C++ 对象间的继承关系(赋值兼容规则)_第1张图片

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

一、三种继承方式:

1.公有继承 public:

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

2.保护继承 protected:

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

3.私有继承 private:

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

C++ 对象间的继承关系(赋值兼容规则)_第2张图片

 C++ 对象间的继承关系(赋值兼容规则)_第3张图片

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

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

例:

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 进行标识。

C++ 对象间的继承关系(赋值兼容规则)_第4张图片

 三、多层继承

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;

按照图示顺序进行构建:

C++ 对象间的继承关系(赋值兼容规则)_第5张图片

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

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;

}

 如图:

C++ 对象间的继承关系(赋值兼容规则)_第6张图片

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

如图:

C++ 对象间的继承关系(赋值兼容规则)_第7张图片

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;
}

创建顺序如下图: 

C++ 对象间的继承关系(赋值兼容规则)_第8张图片

 打来监视器如下图:C++ 对象间的继承关系(赋值兼容规则)_第9张图片

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

如图:

C++ 对象间的继承关系(赋值兼容规则)_第10张图片

而,作为设计人员,我们不想让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. 派生类的对象可以赋值给基类对象

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

C++ 对象间的继承关系(赋值兼容规则)_第11张图片

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

C++ 对象间的继承关系(赋值兼容规则)_第12张图片

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

如图:

C++ 对象间的继承关系(赋值兼容规则)_第13张图片

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

C++ 对象间的继承关系(赋值兼容规则)_第14张图片

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

C++ 对象间的继承关系(赋值兼容规则)_第15张图片

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 回收空间时,会发现只调用了基类的析构函数,并没有调用派生类的析构函数,就会出现内存泄漏问题。

C++ 对象间的继承关系(赋值兼容规则)_第16张图片

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

C++ 对象间的继承关系(赋值兼容规则)_第17张图片  

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

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. 构建顺序:先从左到右,后从上到下

C++ 对象间的继承关系(赋值兼容规则)_第18张图片

C++ 对象间的继承关系(赋值兼容规则)_第19张图片

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

C++ 对象间的继承关系(赋值兼容规则)_第20张图片

你可能感兴趣的:(c++,c++)