我过去使用的基类纯粹是为了使类型信息保持不变(类似于traits类,以及ios_base)。这些类通常没有数据,但只提供常用的类型(可能是装饰原始类型),这个想法是在发生变化时,在一个位置改变类型常量。我一直在想,对于可能从这些类型类继承的接口使用虚拟继承是否有任何优势。类似情况的一个众所周知的例子是可以派生boost :: noncopyable的接口(不是我经常使用boost :: noncopyable作为接口)。
以下是有关案例的一个小例子:
#include <iostream>
#include <memory>
struct Path{};
struct SomeTypeDefs //Or something providing services similar boost::noncopyable
{
typedef std::shared_ptr<Path> PathPtr;
};
struct InterfaceX : SomeTypeDefs
{
virtual PathPtr getPathX() const = 0;
};
struct InterfaceY : SomeTypeDefs
{
virtual PathPtr getPathY() const = 0;
};
struct Impl : InterfaceX, InterfaceY
{
private:
PathPtr getPathY() const override{ return PathPtr{}; }
PathPtr getPathX() const override{ return PathPtr{}; }
};
void foo(const InterfaceX&)
{
std::cout << "foo X" << std::endl;
}
void foo(const InterfaceY&)
{
std::cout << "foo Y" << std::endl;
}
int main()
{
Impl impl;
foo(static_cast<InterfaceX&>(impl));
foo(static_cast<InterfaceY&>(impl));
return 0;
}
在这种情况下,我看不到使用虚拟继承的好处(有没有)?
答案 0 :(得分:1)
警告:意见,可能不会直接回答这个问题..
坦率地说,这种情况可以通过策略类而不是继承来更好地处理!
例如,我会
struct SomeTraits {
typedef std::shared_ptr<Path> PathPtr;
};
// here class is hard-wired to policy
struct InterfaceX
{
virtual SomeTraits::PathPtr getPathX() const = 0;
};
struct InterfaceY
{
virtual SomeTraits::PathPtr getPathY() const = 0;
};
然后你可以这样做:
// here class doesn't really care about specific policy...
template <typename Traits>
struct InterfaceX
{
typedef typename Traits:: PathPtr;
virtual PathPtr getPathX() const = 0;
};
template <typename Traits>
struct InterfaceY
{
typedef typename Traits:: PathPtr;
virtual Traits getPathY() const = 0;
};
这为您提供了很多可能性(请参阅基于策略的设计..)我认为坦率地说比继承更清晰,特别是如果您要定义类型!