c++第十章-(多继承与虚继承)

多继承

class Person
{
public:
    Person(std::string theName);

    void introduce();

protected:
    std::string name;
};

class Teacher : public Person
{
public:
    Teacher(std::string theName,std::string theClass);

    void teach();
    void introduce();

protected:
    std::string classes;
};

class Student : public Person
{
public:
    Student(std::string theName,std::string theClass);

    void attendClass();
    void introduce();
protected:
    std::string classes;
};

Person::Person(std::string theName)
{
    this->name = theName;
}

void Person::introduce()
{
    std::cout << "大家好,我是" << name << ".\n\n";
}

Teacher::Teacher(std::string theName,std::string theClass) : Person(theName)
{
    this->classes = theClass;
}

void Teacher::teach()
{
    std::cout << this->name << "教" << classes << ".\n\n";
}

void Teacher::introduce()
{
    std::cout << "大家好,我是" << name << ",我教" << classes << ".\n\n";
}

Student::Student(std::string theName,std::string theClass) : Person(theName)
{
    this->classes = theClass;
}

void Student::attendClass()
{
    std::cout << name << "加入" << classes << "学习。\n\n";
}

void Student::introduce()
{
    std::cout << "大家好,我是" << name << ",我在" << classes << "学习.\n\n";
}

class TeachingStudent : public Student,public Teacher
{
public:
    TeachingStudent(std::string theName,std::string classTeaching,std::string classAttending);

    void introduce();
};

TeachingStudent::TeachingStudent(std::string theName,std::string classTeaching,std::string classAttending) : Teacher(theName,classTeaching),Student(theName,classAttending)
{

}

void TeachingStudent::introduce()
{
    std::cout << "大家好,我是" << Student::name << ".我教" << Teacher::classes << ",";
    std::cout << "同时我在" << Student::classes << "学习.\n\n";
}

int main(int argc, const char * argv[])
{
    Teacher teacher("小甲鱼","C++入门班");
    Student student("迷途羔羊","C++入门班");
    TeachingStudent teachingStudent("丁丁","C++入门班","C++进阶版");

    teacher.introduce();
    teacher.teach();

    student.introduce();
    student.attendClass();

    teachingStudent.introduce();
    teachingStudent.teach();
    teachingStudent.attendClass();

    return 0;
}

控制台返回结果是:

大家好,我是小甲鱼,我教C++入门班.

小甲鱼教C++入门班.

大家好,我是迷途羔羊,我在C++入门班学习.

迷途羔羊加入C++入门班学习。

大家好,我是丁丁.我教C++入门班,同时我在C++进阶版学习.

丁丁教C++入门班.

丁丁加入C++进阶版学习。

虚继承

TeachingStudent对象里继承了2个不同的classes属性,也就说也继承了2个不同的name属性。

但当我们的预期是同一个人的时候去做2件不同事的时候,就存在分裂多1个不必要的人了!就TeachingStudent类继承于Teacher和Student两个类,因而继承了两组Person类的属性。这个时候Person类的name属性就会引起麻烦。

class Person
{
public:
    Person(std::string theName);

    void introduce();

protected:
    std::string name;
};

class Teacher :  public Person
{
public:
    Teacher(std::string theName,std::string theClass);

    void teach();
    void introduce();

protected:
    std::string classes;
};

class Student : public Person
{
public:
    Student(std::string theName,std::string theClass);

    void attendClass();
    void introduce();
protected:
    std::string classes;
};

Person::Person(std::string theName)
{
    this->name = theName;
}

void Person::introduce()
{
    std::cout << "大家好,我是" << name << ".\n\n";
}

Teacher::Teacher(std::string theName,std::string theClass) : Person(theName)
{
    this->classes = theClass;
}

void Teacher::teach()
{
    std::cout << this->name << "教" << classes << ".\n\n";
}

void Teacher::introduce()
{
    std::cout << "大家好,我是" << name << ",我教" << classes << ".\n\n";
}

Student::Student(std::string theName,std::string theClass) : Person(theName)
{
    this->classes = theClass;
}

void Student::attendClass()
{
    std::cout << name << "加入" << classes << "学习。\n\n";
}

void Student::introduce()
{
    std::cout << "大家好,我是" << name << ",我在" << classes << "学习.\n\n";
}

class TeachingStudent : public Student,public Teacher
{
public:
    TeachingStudent(std::string theName1,std::string theName2,std::string classTeaching,std::string classAttending);//

    void introduce();
};

TeachingStudent::TeachingStudent(std::string theName1,std::string theName2,std::string classTeaching,std::string classAttending) : Teacher(theName1,classTeaching),Student(theName2,classAttending)//
{

}

void TeachingStudent::introduce()
{
    std::cout << "大家好,我是" << Student::name << ".我教" << Teacher::classes << ",";
    std::cout << "同时我在" << Student::classes << "学习.\n\n";
}

int main(int argc, const char * argv[])
{
    Teacher teacher("小甲鱼","C++入门班");
    Student student("迷途羔羊","C++入门班");
    TeachingStudent teachingStudent("丁丁","丹丹","C++入门班","C++进阶版");//

    teacher.introduce();
    teacher.teach();

    student.introduce();
    student.attendClass();

    teachingStudent.introduce();
    teachingStudent.teach();
    teachingStudent.attendClass();

    return 0;
}

控制台打印结果:

大家好,我是小甲鱼,我教C++入门班.

小甲鱼教C++入门班.

大家好,我是迷途羔羊,我在C++入门班学习.

迷途羔羊加入C++入门班学习。

大家好,我是丹丹.我教C++入门班,同时我在C++进阶版学习.

丁丁教C++入门班.

丹丹加入C++进阶版学习。

这个时候,c++发明者为了解决这个问题,提供了“虚继承”(virtual inheritance)。

虚继承的语法:class Teacher : virtual public Person{...},这样做就解决了问题:让Student和Teacher类都虚继承自Person类,编译器将确保从Studnet何Teacher类再派生出来的子类只能拥有一份Person类的属性。

class Person
{
public:
    Person(std::string theName);

    void introduce();

protected:
    std::string name;
};

class Teacher : virtual public Person//虚继承,保证了只保留1份Person类的属性,实际上表明没有继承Person的属性
{
public:
    Teacher(std::string theName,std::string theClass);

    void teach();
    void introduce();

protected:
    std::string classes;
};

class Student : virtual public Person//虚继承,保证了只保留1份Person类的属性,实际上表明没有继承Person的属性
{
public:
    Student(std::string theName,std::string theClass);

    void attendClass();
    void introduce();
protected:
    std::string classes;
};

Person::Person(std::string theName)
{
    this->name = theName;
}

void Person::introduce()
{
    std::cout << "大家好,我是" << name << ".\n\n";
}

Teacher::Teacher(std::string theName,std::string theClass) : Person(theName)
{
    this->classes = theClass;
}

void Teacher::teach()
{
    std::cout << this->name << "教" << classes << ".\n\n";
}

void Teacher::introduce()
{
    std::cout << "大家好,我是" << name << ",我教" << classes << ".\n\n";
}

Student::Student(std::string theName,std::string theClass) : Person(theName)
{
    this->classes = theClass;
}

void Student::attendClass()
{
    std::cout << name << "加入" << classes << "学习。\n\n";
}

void Student::introduce()
{
    std::cout << "大家好,我是" << name << ",我在" << classes << "学习.\n\n";
}

class TeachingStudent : public Student,public Teacher
{
public:
    TeachingStudent(std::string theName,std::string classTeaching,std::string classAttending);

    void introduce();
};

TeachingStudent::TeachingStudent(std::string theName,
                                 std::string classTeaching,
                                 std::string classAttending)
:
Teacher(theName,classTeaching),
Student(theName,classAttending),
Person(theName)//因为之前的Tearcher和Student都是虚继承,所以这里要再次继承于Person类的构造方法
{

}

void TeachingStudent::introduce()
{
    std::cout << "大家好,我是" << name << ".我教" << Teacher::classes << ",";//因为是虚继承,子类只保留1份属性,所以这里可以直接写name
    std::cout << "同时我在" << Student::classes << "学习.\n\n";
}

int main(int argc, const char * argv[])
{
    Teacher teacher("小甲鱼","C++入门班");
    Student student("迷途羔羊","C++入门班");
    TeachingStudent teachingStudent("丁丁","C++入门班","C++进阶版");

    teacher.introduce();
    teacher.teach();

    student.introduce();
    student.attendClass();

    teachingStudent.introduce();
    teachingStudent.teach();
    teachingStudent.attendClass();

    return 0;
}

控制台打印结果:

大家好,我是小甲鱼,我教C++入门班.

小甲鱼教C++入门班.

大家好,我是迷途羔羊,我在C++入门班学习.

迷途羔羊加入C++入门班学习。

大家好,我是丁丁.我教C++入门班,同时我在C++进阶版学习.

丁丁教C++入门班.

丁丁加入C++进阶版学习。

c++第十章-(多继承与虚继承)

时间: 2024-10-07 12:29:07

c++第十章-(多继承与虚继承)的相关文章

【整理】C++虚函数及其继承、虚继承类大小

参考文章: http://blog.chinaunix.net/uid-25132162-id-1564955.html http://blog.csdn.net/haoel/article/details/1948051/ 一.虚函数与继承 1.空类,空类单继承,空类多继承的sizeof #include <iostream> using namespace std; class Base1 { }; class Base2 { }; class Derived1:public Base1

C++ 继承之虚继承与普通继承的内存分布

仅供互相学习,请勿喷,有观点欢迎指出~ class A { virtual void aa(){}; }; class B : public virtual A { char j[3]; //加入一个变量是为了看清楚class中的vfptr放在什么位置 public: virtual void bb(){}; }; class C : public virtual A { char i[3]; public: virtual void cc(){}; }; class C1 : public A

C++ 多继承和虚继承的内存布局(Memory Layout for Multiple and Virtual Inheritance)

警告. 本文有点技术难度,需要读者了解C++和一些汇编语言知识. 在本文中,我们解释由gcc编译器实现多继承和虚继承的对象的布局.虽然在理想的C++程序中不需要知道这些编译器内部细节,但不幸的是多重继承(特别是虚拟继承)的实现方式有各种各样的不太明确的结论(尤其是,关于向下转型指针,使用指向指针的指针,还有虚拟基类的构造方法的调用命令). 如果你了解多重继承是如何实现的,你就能预见到这些结论并运用到你的代码中.而且,如果你关心性能,理解虚拟继承的开销也是非常有用的.最后,这很有趣. :-) 多重

转载:C++ 多继承和虚继承的内存布局

C++ 多继承和虚继承的内存布局[已翻译100%] 英文原文:Memory Layout for Multiple and Virtual Inheritance 标签: <无> run_mei 推荐于 4年前 (共 14 段, 翻译完成于 10-17) 评论 46 分享 收藏 198 参与翻译 (5人) : super0555, polarisxxm, Ley, zaobao, 开源中国吹牛第一仅中文 | 中英文对照 | 仅英文 | 打印此文章 警告. 本文有点技术难度,需要读者了解C++和

C++ 多继承和虚继承的内存布局(转)

转自:http://www.oschina.net/translate/cpp-virtual-inheritance 警告. 本文有点技术难度,需要读者了解C++和一些汇编语言知识. 在本文中,我们解释由gcc编译器实现多继承和虚继承的对象的布局.虽然在理想的C++程序中不需要知道这些编译器内部细节,但不幸的是多重继承(特别是虚拟继承)的实现方式有各种各样的不太明确的结论(尤其是,关于向下转型指针,使用指向指针的指针,还有虚拟基类的构造方法的调用命令). 如果你了解多重继承是如何实现的,你就能

More Effective C++----(24)理解虚拟函数、多继承、虚继承和RTTI所需的代价

Item M24:理解虚拟函数.多继承.虚继承和RTTI所需的代价 C++编译器们必须实现语言的每一个特性.这些实现的细节当然是由编译器来决定的,并且不同的编译器有不同的方法实现语言的特性.在多数情况下,你不用关心这些事情.然而有些特性的实现对对象大小和其成员函数执行速度有很大的影响,所以对于这些特性有一个基本的了解,知道编译器可能在背后做了些什么,就显得很重要.这种特性中最重要的例子是虚拟函数. 当调用一个虚拟函数时,被执行的代码必须与调用函数的对象的动态类型相一致:指向对象的指针或引用的类型

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

多继承和虚继承 1.多继承的优缺点 (1) 多继承可以复用多个类的代码(函数,变量). (2) 多继承会带来二义性问题. // 1. 多继承优缺点 class Flyable { public: void fly() { cout << "飞翔..." << endl; } void sound() { cout << "嗖嗖..." << endl; } }; class Runnable { public: voi

多继承(虚继承)派生类对象内存结构

在这里谈一下虚继承.前面写过派生类对象的内存结构,都是基于VS2010编译器的,不同的编译器对于继承的处理不同,但本质都是一样的. 虚继承是解决共享基类问题的.例如在菱形继承中 如果不使用虚继承,基类A在D中会有两个,这不仅浪费内存,还会造成歧义.使用虚继承就可以解决基类共享的问题. 要想在派生类中共享基类(例如在D对象中只有一个A对象,这时候D对象中的B对象和C对象都可以查找到A,而不是在B对象和C对象中各含有一个A对象). 先看下面一个例子: #include<iostream> usin

多重继承,虚继承,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()