请考虑以下代码,其中B是D通过B1和继承的虚拟基类B2:
#include <iostream>
class B
{
protected:
int x;
protected:
B(int x) : x{x}{std::cout << x << std::endl;}
};
class B1 : virtual public B
{
protected:
B1() : B(0){}
};
class B2 : virtual public B
{
protected:
B2() : B(10){}
};
class D : public B1, public B2
{
public:
D() : B(99), B1(), B2() {}
void print() {std::cout << "Final: " << x << std::endl;}
};
int main() { …Run Code Online (Sandbox Code Playgroud) 昨天,我遇到了这个问题:迫使不合格的名称成为依赖值最初,它似乎是一个与破坏的VC++行为有关的非常具体的问题,但在尝试解决它时,我偶然发现了虚拟继承的使用模式我没有之前遇到过(在我告诉你问题之后,我会在一秒钟内解释).我发现它很有趣,所以我在SO和google上寻找它,但我找不到任何东西.也许,我只是不知道它的正确名称("方法注入"是我的猜测之一),它实际上是众所周知的.这也是我对社区提问的一部分:这是一种常见的使用模式还是另一种已知范式的特例?您是否看到任何可以通过其他解决方案避免的问题/陷阱?
此模式可以解决的问题如下:假设您有一个Morph带有方法的类doWork().在其中doWork(),调用了几个函数,其实现应该由用户选择(这就是调用类的原因Morph).让我们称之为函数变色龙(因为Morph类最终不知道它们将是什么).实现这一目标的一种方法当然是使变色龙成为Morph类的虚方法,这样用户就可以派生出来Morph并覆盖所选择的方法.但是,如果期望用户使用不同的组合来选择不同变色龙的实现,该怎么办呢?然后,对于每个组合,必须定义新类.另外,如果有多个Morph类相同的函数应该是变色龙呢?用户如何重用已经实现的替换?
至于"必须定义多个类"的问题,立即模板跳进了一个人的脑海.用户不能通过将类作为定义所需实现的模板参数来选择他想要的变色龙实现吗?即类似的东西Morph<ReplaceAB>应该有效地取代变色龙,A()并且B()在doWork()某些实施中,留下可能的其他变色龙,例如C(),未触动过.使用C++ 11和可变参数模板,即使组合也不会成为问题:Morph<ReplaceAB, ReplaceC, WhateverMore...>嗯,确实,这种模式可以做什么(参见下面的解释):
#include <iostream>
using namespace std;
// list all chameleons, could also be make some of them
// pure virtual, so a custom implementation is *required*.
struct Chameleons
{
virtual void A() { cout << "Default A" << endl; }
virtual void B() { cout << "Default B" …Run Code Online (Sandbox Code Playgroud)