2017-08-01 97 views
0

我试图实现以下继承关系。联盟虚拟继承

  Variable 
    /  \ 
... GlobalVar LocalVar ... 
     \  /(either) 
     ExtendedVar // Essentially with more fields 

我基本上希望它延长Variable子类中的一个,而选择在运行时做出。虚拟继承并不能完全解决问题。如果ExtendedVar继承GlobalVarLocalVar,并且当我需要调用某个成员funciton时,我无法指定要为该函数使用哪个基类。

此代码似乎工作。

class ExtendedVar : public Variable /* ExtendedVar is-a Variable */ { 
    Variable& var; // wraps a var in it. This is the var to extend. 
    std::string some_field; 
} 

但它在继承中带有一个不必要的副本。或者我可以再多上几门课,例如ExtendedGlobalVarExtendedLocalVar,这对维护显然是不利的。

有没有更好的选择?

+1

https://stackoverflow.com/questions/49002/prefer -composition-over-inheritance – CoryKramer

+1

这实际上并不十分清楚你想要做什么,但是你可能需要''D''中的成员'A *'(或者某个智能变体或'A&')而不是继承。 –

+0

@CoryKramer,感谢您的链接,但我希望A的全部接口,并扩展A的子类之一... – YiFei

回答

2

我基本上想要它扩展变量的一个子类,并在运行时进行选择。

要有运行时多态性,必须间接引用一个对象。基地不能是间接的,但常规的会员可以。因此,你认为继承是不可能的,但组成为:

struct ExtendedVar { 
    std::unique_ptr<Variable> var; 
}; 

或者,我可以有几类,如ExtendedGlobalVar和ExtendedLocalVar,这显然不利于maintainence。

如果这是一个选项(即使是不好的选项),那么它听起来像基地的选择不必在运行时完成。

在这种情况下,你可以用一个模板来生成与您所选择的基类,而不必单独维护每个变种:

template <class Base> 
struct ExtendedVar : Base { 
    // things common to all extended variables 
}; 

ExtendedVar<GlobalVar> an_extended_global_variable; 
+0

CRTP似乎在这里做的伎俩。非常感谢。 – YiFei

+0

等等......我可以为模板化的ExtendedVar有一个通用的基类吗? – YiFei

+0

@YiFei哎呀。我所展示的不是CRTP:D它只是一个普通的模板。采用这种方法,只要模板参数继承公共基础,那么类将从模板实例化。没有编译时检查,但应该可以使用'enable_if'。 – user2079303