避免C++虚拟继承

Avoiding C++ virtual inheritance

本文关键字:继承 虚拟 C++ 避免      更新时间:2023-10-16

>我正在尝试使用实现类的等效层次结构从抽象基类的层次结构继承。我想出如何做到这一点的唯一方法是使用虚拟继承。

/* Foo Interface */
class IFoo
{
public:
virtual void foo() = 0;
virtual ~IFoo() = default;
};
/* Bar Interface */
class IBar : virtual public IFoo
{
public:
virtual void bar() = 0;
virtual ~IBar() = default;
};
/* A specialized Foo */
class SpecificFoo : virtual public IFoo
{
public:
void foo() override { std::cout << "Foo!n"; }
};
/* A specialized Bar */
class SpecificBar : virtual public IBar, virtual public SpecificFoo
{
public:
void bar() override { std::cout << "Bar!n"; }
};
int main()
{
SpecificBar b;
b.bar();
return 0;
}

虽然我并不完全反对使用虚拟继承,但我不确定这是否是正确的方法。如果可能的话,不得不使用dynamic_cast似乎是要避免的事情。有没有更好的方法可以做到这一点?

我已经尝试过适配器模式,但复制/粘贴包装器方法失控了。

我看不到从发布的代码中IBarIFoo子类型的好处。 IMO,最好删除该继承。

/* Foo Interface */
class IFoo
{
public:
virtual void foo() = 0;
virtual ~IFoo() = default;
};
/* Bar Interface */
class IBar 
{
public:
virtual void bar() = 0;
virtual ~IBar() = default;
};
/* A specialized Foo */
class SpecificFoo : public IFoo
{
public:
void foo() override { std::cout << "Foo!n"; }
};
/* A specialized Bar */
class SpecificBar : public IBar
{
public:
void bar() override { std::cout << "Bar!n"; }
};
/* A specialized Foo and Bar */
class SpecificFooAndBar : public IFoo, public IBar
{
public:
void foo() override { std::cout << "Foo!n"; }
void bar() override { std::cout << "Bar!n"; }
};

我想出了一个解决方案,既避免了虚拟继承,又摆脱了代码重复。我使用模板参数来指定基类。

/* Foo Interface */
class IFoo
{
public:
virtual void foo() = 0;
virtual ~IFoo() = default;
};
/* Bar Interface */
class IBar : public IFoo
{
public:
virtual void bar() = 0;
virtual ~IBar() = default;
};
/* A specialized Foo */
template <typename _BaseClass>
class SpecificFooTpl : public _BaseClass
{
public:
void foo() override { std::cout << "Foo!n"; }
};
using SpecificFoo = SpecificFooTpl<IFoo>;
/* A specialized Bar */
class SpecificBar : public SpecificFooTpl<IBar>
{
public:
void bar() override { std::cout << "Bar!n"; }
};
int main()
{
SpecificFoo f;
SpecificBar b;
f.foo();
b.bar();
return 0;
}