C++的虚拟继承(基础)

简介: C++的虚拟继承(基础)

4edc953e2c684bbe819ffa954c899c08.png作者:良知犹存

转载授权以及围观->欢迎添加Wx:Allen-Iverson-me-LYN

前言:本文为C++使用过程中的一些细节知识补充,碎片化的知识.其中有韦东山老师和其他博主一些知识笔记,在此谢谢韦老师以及各博主的文章博客,受益良多.


一、基类成员在派生类中的访问控制属性:

   首先派生类是C++中引入派生类,是为了解决重复代码的问题,通过使用派生类,程序员只需要在已经存在的类中进行继承,只需要修改少量的代码就产生新的类.

   但是继承的时候,因为类成员所属的限定符不同,所以导致继承的时候,访问属性不同.

   下面我们先来描述一下类的三种成员:

  • public (公共成员) ,顾名思义在public限定下的类成员可以被类里面的成员函数引用,亦可以类之外的其他函数引用.所以在继承类,public成员可以完整属性的被继承.
  • private(私有成员),特指在类中私用的成员,一般为类的数据成员.这些数据成员一般会被在public的成员函数进行访问.所以私有成员只能被定义的类的成员函数进行引用,其他类无法进行访问,此处友员类或者友员函数除外.
  • protect(受保护的成员),此限制符下的成员访问属性介于public与private之间.protect标识成员不能被类外访问,但可以通过继承的派生类进行访问.

类的几种访问限制符了解完,下面开始介绍继承中我们继承成员的具体访问情况.

  • 第一种public继承,由于public是公开的特性,类之外也可以被引用,所以当派生类继承为public,private或者protect,public下面的成员会随着派生类的限定符进行划归,也就是继承到public就是public成员,继承到protect就是protect成员,继承到private就是private成员.
  • 第二种protect继承,由于继承父类中该成员就是属于protect所以派生的子类也会受到限制,该成员由于父类已经进行限制,所以继承的子类到public是无法完整获得任意访问的属性,所以如下图,继承到public中的protect成员依旧有protect的属性限制,继承到protect和private限制的时候,类成员按照子类的限制符进行访问。
  • 第三种private继承,由于private成员是最私密的限制,所以继承之后全部为private的权限。

综上所述,我们发现,继承的时候该成员是按照继承的父类以及继承到的子类的成员限制最大的类型进行继承的。

4edc953e2c684bbe819ffa954c899c08.png

   继承示例:

class D{......};
class B: public D{......};

注:继承的时候如果不写public默认就会私有继承。


二、虚拟继承

   多重继承容易出现多义,另外多重继承中出现环继承,也为了节省内存空间,所以C++引入虚拟继承。

多重继承多义性的代码片段,参考代码韦东山C++

#include <iostream>
#include <string.h>
#include <unistd.h>
/*多态*/
using namespace std;
class Human{
private:
    int a;
public:
    void eating(void){
        cout<<"use hand to eat"<<endl;
    }
};
class Englishman : public Human{
public:
    void eating(void){
        cout<<"use knife to eat"<<endl;
    }
};
class Chinese : public Human{
public:
    void eating(void){
        cout<<"use chopsticks to eat"<<endl;
    }
};
void test_eating(Human &h)
{
    h.eating();
}
int main(int argc,char **argv)
{
    Human h;
    Englishman e;
    Chinese c;
    test_eating(h);
    test_eating(e);
    test_eating(c);
    cout<<"Humen       length:="<<sizeof(h)<<endl;
    cout<<"Englishman  length:="<<sizeof(e)<<endl;
    cout<<"Chinese     length:="<<sizeof(c)<<endl;
    return 0;
}

4edc953e2c684bbe819ffa954c899c08.png

   多重继承使得程序出现二义性,可以用virtual进行虚拟继承来解决,但是由于多重继承会使程序变得复杂,所以不建议使用多重继承。

#include <iostream>
#include <string.h>
#include <unistd.h>
/*多态*/
using namespace std;
class Human{
private:
    int a;
public:
    virtual void eating(void){
        cout<<"use hand to eat"<<endl;
    }
    ~Human(){
        cout<<"~Human()"<<endl;
    }
};
class Englishman : public Human{
public:
    void eating(void){
        cout<<"use knife to eat"<<endl;
    }
    ~Englishman(){
        cout<<"~Englishman()"<<endl;
    }
};
class Chinese : public Human{
public:
    void eating(void){
        cout<<"use chopsticks to eat"<<endl;
    }
    ~Chinese(){
        cout<<"~Chinese()"<<endl;
    }
};
void test_eating(Human &h)
{
    h.eating();
}
int main(int argc,char **argv)
{
    Human h;
    Englishman e;
    Chinese c;
    test_eating(h);
    test_eating(e);
    test_eating(c);
    cout<<"Humen       length:="<<sizeof(h)<<endl;
    cout<<"Englishman  length:="<<sizeof(e)<<endl;
    cout<<"Chinese     length:="<<sizeof(c)<<endl;   
    return 0;
}

4edc953e2c684bbe819ffa954c899c08.png

环装继承:

class A{......};
class B: public A{......};
class C: public A{......};
class D: public B, public C{.....};
class A
class B:public virtual A;
class C:public virtual A;
class D:public B,public C;

   降低内存使用的实际原理:虚拟基类中的构造函数只执行一次。并且构造的时候虚拟基类先执行。

using namespace std;
class Human {
private:
  int a;
public:
  virtual void eating(void) { cout<<"use hand to eat"<<endl; }
  virtual ~Human() { cout<<"~Human()"<<endl; }
};
class Englishman : public Human {
public:
  void eating(void) { cout<<"use knife to eat"<<endl; }
  virtual ~Englishman() { cout<<"~Englishman()"<<endl; }
};
class Chinese : public Human {
public:
  void eating(void) { cout<<"use chopsticks to eat"<<endl; }
  virtual ~Chinese() { cout<<"~Chinese()"<<endl; }/*析构函数也应该为虚拟函数*/
};
void test_eating(Human h){
  h.eating();
}
int main(int argc, char **argv){
  Human* h = new Human;
  Englishman* e = new Englishman;
  Chinese* c = new Chinese;
  Human *p[3] = {h, e, c};
  int i;
  for (i = 0; i < 3; i++)
  {
    p[i]->eating();
    delete p[i];
  }
  return 0;
}
目录
相关文章
|
4月前
|
编译器 C++
【C++】详解C++的继承
【C++】详解C++的继承
|
1月前
|
安全 程序员 编译器
【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则
【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则
81 11
|
1月前
|
C++
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
53 1
|
1月前
|
C++
C++番外篇——虚拟继承解决数据冗余和二义性的原理
C++番外篇——虚拟继承解决数据冗余和二义性的原理
39 1
|
1月前
|
安全 编译器 程序员
C++的忠实粉丝-继承的热情(1)
C++的忠实粉丝-继承的热情(1)
18 0
|
1月前
|
编译器 C++
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
30 0
|
1月前
|
程序员 C++
C++入门11——详解C++继承(菱形继承与虚拟继承)-1
C++入门11——详解C++继承(菱形继承与虚拟继承)-1
32 0
|
2月前
|
C++
C++(二十)继承
本文介绍了C++中的继承特性,包括公有、保护和私有继承,并解释了虚继承的作用。通过示例展示了派生类如何从基类继承属性和方法,并保持自身的独特性。此外,还详细说明了派生类构造函数的语法格式及构造顺序,提供了具体的代码示例帮助理解。
|
2月前
|
C++
c++继承层次结构实践
这篇文章通过多个示例代码,讲解了C++中继承层次结构的实践应用,包括多态、抽象类引用、基类调用派生类函数,以及基类指针引用派生类对象的情况,并提供了相关的参考链接。
|
3月前
|
编译器 C++ 索引
C++虚拟成员-虚函数
C++虚拟成员-虚函数