我一直试图找到这个问题的答案,但我不能(我甚至不知道如何正确地制定这个问题)所以我决定在StackOverflow上写我的第一篇文章=)。
上下文如下:
我有这个父类:
class Parent
{
public:
Parent(){};
void foo(void)
{
//Do some common things
bar();
//Do some more common things
};
protected:
virtual void bar(void) = 0;
};
我想创建一个无限量的派生Childs:
class Child1 : public Parent
{
public:
Child1() : Parent(), child1Variable(0) {};
protected:
virtual void bar(void) = 0;
private:
uint32_t child1Variable;
};
class Child2 : public Parent
{
public:
Child2() : Parent(), child2Variable(0) {};
protected:
virtual void bar(void) = 0;
private:
uint32_t child2Variable;
};
.
.
.
class ChildN : public Parent
{
public:
ChildN() : Parent(), childNVariable(0) {};
protected:
virtual void bar(void) = 0;
private:
uint32_t childNVariable;
};
原因主要是不重复父foo()
然后我想创建我的最终可实例化类,例如:
class ExampleFinal : public Child1, public Child3, public Child27
{
//How to define Child1::bar(), Child3::bar() and Child27::bar() ??
private:
void bar(void); //????
};
所以问题是:
ExampleFinal::Child1::bar
,ExampleFinal::Child3::bar
,... 最终目标是能够做到这样的事情:
ExampleFinal test;
test.Child1::foo(); //should end up on "ExampleFinal::Child1::bar"
test.Child3::foo(); //should end up on "ExampleFinal::Child3::bar"
谢谢!
答案 0 :(得分:2)
实现ExampleFinal::bar()
(旁注:bar(void)
是一个在C ++中没用的C-ism)会覆盖你一次声明的所有bar
。如果您想拥有不同的版本,则需要插入另一层类:
struct GrandChild1 : Child1 {
void bar() override { /*...*/ }
};
// And so on...
struct ExampleFinal : GrandChild1, GrandChild3, GrandChild27 {
// Nothing needed here.
};
然后您描述的行为将起作用。但请注意,您的继承图表示ExampleFinal
每个Parent
有一个Child
子对象。这本身不是问题,但可能无法模拟你想要的东西 - 也许你需要虚拟继承,但要注意兔子洞。
如果要保留ChildN::bar
内所有ExampleFinal
的覆盖,您可以添加标记分派来识别它们,但需要再花一次虚拟呼叫:
struct Parent {
void foo() {
bar();
};
protected:
template <class Child>
struct tag { };
virtual void bar() = 0;
};
struct Child1 : Parent {
protected:
virtual void bar(tag<Child1>) = 0;
void bar() final override {
return bar(tag<Child1>{});
}
int child1Var;
};
struct Child2 : Parent {
protected:
virtual void bar(tag<Child2>) = 0;
void bar() final override {
return bar(tag<Child2>{});
}
int child2Var;
};
struct ExampleFinal : Child1, Child2 {
protected:
using Parent::tag;
void bar(tag<Child1>) final override {
std::cout << "Child1::bar\n";
}
void bar(tag<Child2>) final override {
std::cout << "Child2::bar\n";
}
};
请注意,bar()
到bar(tag<ChildN>)
网桥很容易隐藏在宏后面。如果您想避免第二次虚拟呼叫的费用,也可以在此处应用CRTP。