不可或缺 Windows Native (22) - C++: 多重继承, 虚基类
作者:webabcd
介绍
不可或缺 Windows Native 之 C++
- 多重继承
- 虚基类
示例
1、基类 1
CppBase1.h
#pragma once #include <string> #include "CppBaseVirtual.h" using namespace std; namespace NativeDll { // virtual 代表 CppBaseVirtual 是 CppBase1 的虚基类(虚基类是在声明派生类时,指定继承方式时声明的) class CppBase1 : virtual public CppBaseVirtual { protected: string Name; float Salary; public: CppBase1(int number, string name, float salary); }; }
CppBase1.cpp
/* * 基类 1 */ #include "pch.h" #include "CppBase1.h" using namespace NativeDll; CppBase1::CppBase1(int number, string name, float salary) :CppBaseVirtual(number), Name("cppbase1 " + name), Salary(salary) { }
2、基类 2
CppBase2.h
#pragma once #include <string> #include "CppBaseVirtual.h" using namespace std; namespace NativeDll { // virtual 代表 CppBaseVirtual 是 CppBase2 的虚基类(虚基类是在声明派生类时,指定继承方式时声明的) class CppBase2 : virtual CppBaseVirtual { protected: string Name; int Age; public: CppBase2(int number, string name, int age); }; }
CppBase2.cpp
/* * 基类 2 */ #include "pch.h" #include "CppBase2.h" using namespace NativeDll; CppBase2::CppBase2(int number, string name, int age) :CppBaseVirtual(number), Name("cppbase2 " + name), Age(age) { }
3、虚基类
CppBaseVirtual.h
#pragma once #include <string> using namespace std; namespace NativeDll { class CppBaseVirtual { private: int Number; public: CppBaseVirtual(int number); }; }
CppBaseVirtual.cpp
/* * 用于演示虚基类 * * 注: * 1、虚基类并不是在声明基类时声明的,而是在声明派生类时,指定继承方式时声明的 * 2、一个基类可以在生成一个派生类时作为虚基类,也可以在生成一个派生类时不作为虚基类 */ #include "pch.h" #include "CppBaseVirtual.h" using namespace NativeDll; CppBaseVirtual::CppBaseVirtual(int number) :Number(number) { }
4、派生类
CppDerived.h
#pragma once #include <string> #include "CppBase1.h" #include "CppBase2.h" using namespace std; namespace NativeDll { class CppDerived : public CppBase1, public CppBase2 { public: CppDerived(int number, string name, float salary, int age); string Show(); }; }
CppDerived.cpp
/* * 派生类 * * * 在多重继承的情况下: * 1、如果 A 是 B C D E 的基类,F 同时继承了 B C D E,那么实例化 F 时会保存 4 份 A 成员 * 2、如果 A 是 B 的基类,A 是 C D E 的虚基类(虚基类会使得在继承间接共同基类时只保留一份成员),F 同时继承了 B C D E,那么实例化 F 时会保存 2 份 A 成员(从 C D E 的路径上保留一份,从 B 的路径上保留一份) * * * 本例中: * 1、CppBaseVirtual 是 CppBase1 和 CppBase2 的虚基类 * 2、CppDerived 继承了 CppBase1 和 CppBase2(多重继承) * 3、此种情况,实例化 CppDerived 只会保留一份 CppBaseVirtual 成员(因为 CppBaseVirtual 是 CppBase1 和 CppBase2 的虚基类) * 4、C++ 编译器只会执行最后的派生类(CppDerived)对虚基类(CppBaseVirtual)的构造函数的调用,而忽略虚基类的直接派生类(CppBase1 和 CppBase2)对虚基类的构造函数的调用,这就保证了虚基类的数据成员不会被多次初始化 */ #include "pch.h" #include "CppDerived.h" #include "cppHelper.h" using namespace NativeDll; // 在无虚基类的情况下,派生类的构造函数中只需负责对其直接基类初始化 // 如果有虚基类,且虚基类中定义了带参数的构造函数,且没有定义默认构造函数,那么派生类不仅要负责对其直接基类进行初始化,还要负责对虚基类初始化 CppDerived::CppDerived(int number, string name, float salary, int age) :CppBaseVirtual(number), CppBase1(number, name, salary), CppBase2(number, name, age) { } string CppDerived::Show() { // 关于多重继承的二义性(ambiguous),如果派生类同时继承的多个基类有相同的成员,则调用这些成员时需显式指定其基类 return CppBase1::Name + " " + float2string(Salary) + " " + int2string(Age); // 另外:当然,如果派生类与多个基类有相同成员的话,那么基类中的这些与派生类相同的成员都会被隐藏掉(即派生类中的成员会覆盖基类中的成员) }
5、示例
CppClass6.h
#pragma once #include <string> using namespace std; namespace NativeDll { class CppClass6 { public: string Demo(); }; }
CppClass6.cpp
/* * 多重继承(multiple inheritance), 虚基类(virtual base class) */ #include "pch.h" #include "CppClass6.h" #include "CppDerived.h" using namespace NativeDll; string CppClass6::Demo() { CppDerived derived(0, "webabcd", 100.0f, 35); string result = derived.Show(); // cppbase1 webabcd 100.00 35 return result; }
OK
[源码下载]