我使用的库有很多类型,所有类型都来自相同的2个接口:
class Huey : public IDuck, public ICartoonCharacter
{
...
};
class Dewey : public IDuck, public ICartoonCharacter
{
...
};
class Louie : public IDuck, public ICartoonCharacter
{
...
};
我想将所有上述类型的对象存储在包装类中,并将该包装类的对象粘贴到容器中。当然,我应该能够从我的包装类中调用属于这两个接口的方法。
我有什么选择?我能想到
IDuck *
存储在我的包装器中,并将dynamic_cast-存储到ICartoonCharacter
,或boost::any
之类的内容,同时使我的包装器成为类模板,并使用几个static_asserts
来确保模板参数继承自IDuck
和ICartoonCharacter
。但这两种选择都没有特别吸引人。有什么想法吗?
two interfaces, multiple inheritance combine into one container?是一个相关的问题,但James Kanze的回答对我不起作用,因为我不能改变这三个类。
编辑:不要经常使用多重继承,忘记了语法。现在从两个接口继承public
。
编辑:现在使用dynamic_cast而不是static_cast(这将无效)。
编辑:我发现Mike Seymour和Matthieu M的答案都很有希望。一旦我编码完毕,我会接受他们的一个答案。谢谢!答案 0 :(得分:5)
一个简单的选择是在包装器中存储两个指针:
struct CartoonDuckWrapper {
IDuck * duck;
ICartoonCharacter * toon;
template <class CartoonDuck>
CartoonDuckWrapper(CartoonDuck & cd) : duck(&cd), toon(&cd) {}
};
没有特别需要使用static_assert
来检查CartoonDuck
是否从两个基类继承,尽管这可能比仅仅让指针转换失败提供更好的诊断。
如果基类是多态的(可能是接口,它们可能是接口),您可以使用dynamic_cast
将一个指针转换为一个指针来节省一个指针的空间,以换取运行时成本。其他。 static_cast
不能用于基类之间的这种“交叉投射”。
答案 1 :(得分:3)
作为编程中的所有问题,您可以通过添加一个更多级别的间接来解决它。
class ICartoonDuck: public IDuck, public ICartoonCharacter {};
template <typename T>
class CartoonDuck: public ICartoonDuck {
public:
explicit CartoonDuck(T t): _t(std::move(t)) {}
// IDuck interface
virtual void foo() override { t.foo(); }
// ICartoonCharacter interface
virtual void bar() override { t.bar(); }
private:
T _t; // or any ownership scheme that makes sense
}; // class CartoonDuck
template <typename T>
CartoonDuck<T> makeCartoonDuck(T t) { return CartoonDuck(std::move(t)); }
template <typename T, typename... Args>
std::unique_ptr<CartoonDuck<T>> makeUniqueCartoonDuck(Args&&...) {
return std::unique_ptr<CartoonDuck<T>>(new T(std::forward<Args>()...);
}
现在,您可以愉快地将std::unique_ptr<ICartoonDuck>
存储在容器中。
这可以用作:
std::vector<std::unique_ptr<ICartoonDuck>> cartoonDucks;
cartoonDucks.push_back(makeUniqueCartoonDuck<Huey>());
cartoonDucks.push_back(makeUniqueCartoonDuck<Dewey>());
cartoonDucks.push_back(makeUniqueCartoonDuck<Louie>());
for (std::unique_ptr<ICartoonDuck> const& cd: cartoonDucks) {
cd->foo();
cd->bar();
}
答案 2 :(得分:2)
创建一个中间类:
class ILuckyDuck: public IDuck, ICartoonCharacter //...
使用:
class Huey : public ILuckyDuck //...
etc ,并存储:
std::vector<std:shared_ptr<ILuckyDuck>> donald;