基于http://en.wikipedia.org/wiki/Virtual_inheritance
class Animal
{
...
};
// Two classes virtually inheriting Animal:
class Mammal : public virtual Animal
{
...
};
Run Code Online (Sandbox Code Playgroud)
我还看到书籍使用以下语法,
class Mammal : virtual public Animal
{
...
};
Run Code Online (Sandbox Code Playgroud)
问题>哪个是C++标准?
谢谢
此代码被(至少)MSVC,ICC和GCC拒绝:
class A {
public:
A( int ) { }
};
class B: virtual public A {
public:
//B(): A( -1 ) { } // uncomment to make it compilable
virtual void do_something() = 0;
};
class C: public B {
public:
C(): A( 1 ) { }
virtual void do_something() { }
};
int main() {
C c;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在...的基础上
error : no default constructor exists for class "A"
class B: virtual public A {
^
detected …Run Code Online (Sandbox Code Playgroud) struct D
{
virtual void m() const = 0;
};
struct D1 : public virtual D { };
struct D2 : public virtual D { };
struct B : public D2
{
B() { }
B(int val) : B() { }
void m() const { }
};
struct A : public B, public D1
{
A() : B(0) { }
};
int main()
{
A a;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用上面的代码我遇到MSVC 2013编译器崩溃.使用GCC 4.7.2编译时,它运行时没有崩溃.类的层次结构如下所示.
D
/ \
D1 D2
| |
\ …Run Code Online (Sandbox Code Playgroud) c++ virtual-inheritance visual-c++ c++11 delegating-constructor
我最近在接受采访时询问了有关虚拟功能和多重继承的对象布局.
我在没有涉及多重继承的情况下如何实现它的上下文中解释了它(即编译器如何生成虚拟表,在每个对象中插入指向虚拟表的秘密指针等等).
在我看来,我的解释中缺少一些东西.
所以这里有问题(见下面的例子)
示例代码:
class A {
public:
virtual int funA();
private:
int a;
};
class B {
public:
virtual int funB();
private:
int b;
};
class C : public A, public B {
private:
int c;
};
Run Code Online (Sandbox Code Playgroud)
谢谢!
c++ multiple-inheritance virtual-inheritance vtable memory-layout
让我们假设一些无法触及的(遗留)代码声明
struct B{
public:
void f(){}
};
Run Code Online (Sandbox Code Playgroud)
让我们假设有
struct A{
public:
virtual void f()=0;
};
Run Code Online (Sandbox Code Playgroud)
是否有可能使A子类调用B :: f而不显式调用f(),即代替
struct C: public A, public B{
void f(){
B::f();
}
};
Run Code Online (Sandbox Code Playgroud)
有类似的东西
struct C:virtual public A,virtual public B{
};
Run Code Online (Sandbox Code Playgroud)
(注意,最后一个类是抽象的,因为没有定义编译器A :: f)
我制作了如下测试代码:
#include <iostream>
using namespace std;
#ifndef interface
#define interface struct
#endif
interface Base
{
virtual void funcBase() = 0;
};
interface Derived1 : public Base
{
virtual void funcDerived1() = 0;
};
interface Derived2 : public Base
{
virtual void funcDerived2() = 0;
};
interface DDerived : public Derived1, public Derived2
{
virtual void funcDDerived() = 0;
};
class Implementation : public DDerived
{
public:
void funcBase() { cout << "base" << endl; }
void funcDerived1() { cout << …Run Code Online (Sandbox Code Playgroud) c++ inheritance interface multiple-inheritance virtual-inheritance
我有一个带有两个钻石的类层次结构,因为必须扩展装饰器模式中的所有类(它们已经虚拟扩展):
namespace _sandbox {
class A {
public:
virtual ~A() {}
virtual void foo()=0;
};
class ADecorator : public virtual A {
private:
A* decoratedA;
public:
ADecorator(A* a) : decoratedA(a) {}
void foo() {return decoratedA->foo();}
};
class AImpl : public virtual A {
public:
void foo() {};
};
class B : public virtual A {
public:
virtual ~B() {}
virtual void bar()=0;
};
class BDecorator : public ADecorator, public B {
private:
B* decoratedB; //Copy of the pointer with a …Run Code Online (Sandbox Code Playgroud) 基本问题:是否可以避免必须显式调用每个虚拟基类的(非默认)构造函数?
背景:我正在开发围绕Windows COM对象的一些类型安全的C++包装器类.我目前的方法是有一个CBaseCOMWrapper类封装一个IUnknown对象进行引用计数.然后,我有一个CCOMWrapper模板类所继承CBaseCOMWrapper,它定义一个包装为特定COM类型(即IDXGIObject,ID3D11Device等).最后,单独的类从这些包装模板继承来提供实际的/额外的功能(即CDXGIObject,CD3D11Device).
例如,我有以下类(成员省略):
class CBaseCOMWrapper { };
template<typename T> // here, T should inherit from IUnknown
class CCOMWrapper : public virtual CBaseCOMWrapper { };
class CDXGIObject : public virtual CCOMWrapper<IDXGIObject> { };
template<>
class CCOMWrapper<IDXGIAdapter> : public virtual CCOMWrapper<IDXGIObject> { };
class CDXGIAdapter : public virtual CCOMWrapper<IDXGIAdapter> { };
Run Code Online (Sandbox Code Playgroud)
这是类型层次结构的对应图:

左列是实际对象,中间列是瘦COM包装器,右列是实际COM对象.实线箭头表示继承,虚线箭头表示封装.
我使用模板特化CCOMWrapper来在中间提供父子关系.
问题:包装器类假定一个指向COM对象的非NULL(也就是有效)指针,所以我不能有一个默认的构造函数.因为层次结构充满了"钻石",所以大部分遗传都是虚拟的; 这意味着每个类的构造函数都必须调用构造函数.因此,在上面的例子中,构造函数CDXGIAdapter必须调用构造函数CCOMWrapper<IDXGIAdapter>, …
当我尝试访问从虚拟基类继承的派生类对象的内存布局时,出了点问题.
编程环境:GNU/Linux 3.19.0-32-generic,x86_64
编译器:gcc 4.8.4
//virtual base class
class Base {
public :
virtual void f() {
cout << "Base::f()" << endl;
}
private:
long x;
};
//derived class
class Derived : public virtual Base {
public:
virtual void f() {
cout << "Derived::f()" << endl;
}
private:
long y;
};
int main() {
typedef void (*FUNC)(void);
Derived d;
//In my machine, sizeof(long) == sizeof(pointers). My code below is neither portable nor concise. You can just read the annotation.
//dereference …Run Code Online (Sandbox Code Playgroud) 为什么打印20000?代码在继承序列中一直显式调用特定的基础构造函数,但忽略指定的构造函数并使用默认构造函数.
#include <iostream>
struct Car
{
Car() : price(20000) {}
Car(double b) : price(b*1.1) {}
double price;
};
struct Toyota : public virtual Car
{
Toyota(double b) : Car(b) {}
};
struct Prius : public Toyota
{
Prius(double b) : Toyota(b) {}
};
int main(int argc, char** argv)
{
Prius p(30000);
std::cout << p.price << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud) c++ ×10
inheritance ×5
c++11 ×2
constructor ×2
vtable ×2
abi ×1
com ×1
eclipse ×1
eclipse-cdt ×1
g++ ×1
interface ×1
visual-c++ ×1