C++中对C的扩展学习新增内容———面向对象(继承)多继承和虚继承

多继承和虚继承

1、多继承的优缺点

(1) 多继承可以复用多个类的代码(函数,变量)。

(2) 多继承会带来二义性问题。

// 1. 多继承优缺点
class Flyable
{
public:
    void fly()
    {
        cout << "飞翔..." << endl;
    }

    void sound()
    {
        cout << "嗖嗖..." << endl;
    }
};

class Runnable
{
public:
    void run()
    {
        cout << "跑步..." << endl;
    }

    void sound()
    {
        cout << "刺啦..." << endl;
    }
};

class SuperMan : public Flyable, public Runnable {};
void test01()
{
    SuperMan sm;
    sm.fly();
    sm.run();

    // 1. 多继承可以复用多个类的代码(函数、 变量)
    // 2. 多继承带来二义性问题.
    // sm.sound();
    sm.Flyable::sound();
    sm.Runnable::sound();
}

2、菱形继承问题

1、菱形问题会造成空间浪费。

2、菱形继承问题会产生二义性。

// 2. 菱形继承问题
class Animal
{
public:
    int m_animal;
};

class Sheep : public Animal
{
public:
    int m_sheep;
};

class Tuo : public Animal
{

public:
    int m_tuo;
};

class SheepTuo : public Sheep, public Tuo
{
};

void test02()
{
    // 1. 空间浪费
    // 2. 二义性
    SheepTuo st;
    // st.m_animal;
}

3、虚继承

(1) 当发生虚继承的时候,编译器会在子类中安插一个vbptr指针。

(2) 指针指向一张记录着公共数据相对于vbptr指针的偏移量。

(3) 根据偏移量就可以找到公共部分的数据。

(4) 虚继承会带来程序额外的开销,但是解决了菱形继承的问题。

(5) 虚继承中C++编译器要求没一个子类都能够初始化虚基类数据。

(6) 虚继承主要是为了解决菱形继承问题,如果没有发生菱形继承问题,不建议使用虚继承。

(7) 不建议大家大量使用多继承,允许多接口继承一般不会多继承(任何多继承问题都可以用单继承来解决)

// 3. 虚继承 使用virtual关键字

class Animal
{
public:
    Animal(int)
    {

    }
public:
    int m_animal;
};

class Sheep :  virtual public Animal
{
public:
    Sheep() : Animal(10) {}
public:
    int m_sheep;
};

class Tuo : virtual public Animal
{
public:
    Tuo() : Animal(10) {}
public:
    int m_tuo;
};

class SheepTuo : public Sheep, public Tuo
{
public:
    SheepTuo() : Animal(10) {}
};

void test03()
{
    SheepTuo st;
    st.m_animal;
    st.Sheep::m_animal;
    st.Tuo::m_animal;

    Sheep s;
    s.m_animal;
}

原文地址:https://www.cnblogs.com/yyslif/p/11758754.html

时间: 2024-12-14 08:44:20

C++中对C的扩展学习新增内容———面向对象(继承)多继承和虚继承的相关文章

C++中对C的扩展学习新增内容———面向对象(封装)

面向对象(封装) 1.对封装的理解: 1.封装就是把变量和函数放在一起统一表示某一个食物. class 2.给类内部的成员增加访问控制权限. 3.封装的语法就是class定义一个类. 2.给对象成员增加访问控制权限public和private: 1.类的内部没有权限之分,类内的成员函数可以访问私有成员变量,类的外部才有权限. 2.如果只是提供类内部的函数使用的变量和函数,建议定义为private私有属性. 3.如果我们写的成员函数需要外部调用,我们可以将其定义为共有属性public. 3.str

C++中对C的扩展学习新增语法——内联函数以及函数参数

内联函数以及函数参数 内联函数 使用 inline 关键字必须和函数体放在一起. 内联函数具有内部链接属性. 内联函数会被编译器在编译阶段替换到函数调用的地方. 可以把内联函数定义写到头文件中,多个cpp包含时不会引起重定义. 如果出现连接错误: 使用第三方库,没有将其库代码配置到项目,所以导致编译器找不到实现(变量定义,函数定义) 本身自己只写了声明,根本没有定义实现. 变量本身.函数本身具有内部链接属性,此函数或者变量只能在当前文件访问. 函数参数 函数参数的作用 兼容C语言中不规范的语法

C++中对C的扩展学习新增语法——引用

引用 引用的好处: 1.引用的好处 C++使用结构体,不需要再使用 typedef. 2.值传递是将实参进行拷贝,赋值给形参,如果对象比较大,每次拷贝效率比较低,并且函数内部无法修改外部变量的值,能力较弱.若使用地址传递无论数据大小,每次只需要传递指针大小的数据,传递效率较高,函数具有修改外部变量的能力(const 指针). 而引用即可以有值传递简洁的语法,又可以兼顾指针传递的效率. 代码实现: 引用的语法: 基本类型及结构体引用: 对数组引用: 对指针的引用: 注意事项: 1.&在此不是求地址

多重继承,虚继承,MI继承中虚继承中构造函数的调用情况

先来测试一些普通的多重继承.其实这个是显而易见的. 测试代码: [cpp] view plain copy print? //测试多重继承中派生类的构造函数的调用顺序何时调用 //Fedora20 gcc version=4.8.2 #include <iostream> using namespace std; class base { public: base() { cout<<"base created!"<<endl; } ~base()

C++中虚继承类构造函数的正确写法

最近工作中某个软件功能出现了退化,追查下来发现是一个类的成员变量没有被正确的初始化.这个问题与C++存在虚继承的情况下派生类构造函数的写法有关.在此说明一下错误发生的原因,希望对更多的人有帮助. 我们代码中存在虚继承的类的继承结构与下图类似,并不是教科书中经典的菱形结构.从 Intermediate1 和 Intermediate3 到Base2 的继承都是虚继承.Base1 和 Base2 都包含一些成员变量,并提供了相应的构造函数接受指定的初始化值.Base2 还有一个缺省构造函数,把其成员

C++学习之虚函数继承和虚继承

虚函数的定义要遵循以下重要规则: 1.如果虚函数在基类与派生类中出现,仅仅是名字相同,而形式参数不同,或者是返回类型不同,那么即使加上了virtual关键字,也是不会进行晚绑定的. 2.只有类的成员函数才能说明为虚函数,因为虚函数仅适合用与有继承关系的类对象,所以普通函数不能说明为虚函数. 3.静态成员函数不能是虚函数,因为静态成员函数的特点是不受限制于某个对象. 4.内联(inline)函数不能是虚函数,因为内联函数不能在运行中动态确定位置.即使虚函数在类的内部定义定义,但是在编译的时候系统仍

ExtJS学习-----------Ext.Array,ExtJS对javascript中的Array的扩展

关于ExtJS对javascript中的Array的扩展.能够參考其帮助文档,文档下载地址:http://download.csdn.net/detail/z1137730824/7748893 因为Array中的方法过多.将当中的部分方法设计实例进行学习.实例地址:http://blog.csdn.net/z1137730824/article/details/38797257 (1)Ext.Array中的方法 clean( Array array ) : Array 过滤掉数组里的空值,空值

每日学习心得:SharePoint 为列表中的文件夹添加子项(文件夹)、新增指定内容类型的子项、查询列表中指定的文件夹下的内容

前言: 这里主要是针对列表中的文件下新增子项的操作,同时在新建子项时,可以为子项指定特定的内容类型,在某些时候需要查询指定的文件夹下的内容,针对这些场景都一一给力示例和说明,都是一些很小的知识点,希望能够对大家有所帮助. 1.   在列表中为列表项添加子项 为列表添加子项大家都很熟悉,但是如何为列表项添加子项呢?例如列表项是一个文件夹,如何为该文件夹添加子项呢?这里就用到了List.AddItem()方法,具体示例如下: 首先我们要获取列表中的子项: SPListItem root_item=l

ExtJS学习-----------Ext.String,ExtJS对javascript中的String的扩展

关于ExtJS对javascript中的String的扩展,能够參考其帮助文档,文档下载地址:http://download.csdn.net/detail/z1137730824/7748893 以下对当中的部分方法进行介绍: (1)capitalize capitalize( String string ) : String 返回一个字符串.该字符串中第一个字母为大写字母 Parameters string : String 要转换的字符串 Returns String 转换后的字符串 (2