避免模​​糊问题c ++

时间:2014-11-13 09:32:44

标签: c++ ambiguous

我希望使用一个助手类,它只能为给定的模板参数创建几个Qt typedef别名。由于我希望访问Base以及Derived,因此我的当前设计情况非常快,而且很常见。不确定这个问题是否在某种程度上可以解决,仍然给它一个机会。例如:

template <class T> class SmartAlias
{
public:
    typedef QSharedPointer<T> Shared;
};

class Base : public SmartAlias<Base>
{
};

class Derived : public Base, public SmartAlias<Derived>
{
};

Base::Shared base;  // Normally works
Derived::Shared derived;  // ambiguous problem

任何更好的解决方案的想法?感谢。

内容/ UPDATE /溶液

总而言之,如果有人希望使用它,请使用Anton Savin的想法,也可以使用虚拟继承扩展多重继承:

#include <vector>

template <typename T, typename... MyBases> class SmartAlias :  virtual public MyBases... {
public:
    typedef std::vector<T> Shared;
};

class Base : public SmartAlias<Base>
{
};

class Derived : public SmartAlias<Derived, Base>
{
};

class MiniBase : public SmartAlias<MiniBase> {};

class MiniDerived : public SmartAlias<MiniDerived, MiniBase, Derived> { 
public: 
    MiniDerived() : MiniBase(), Derived() 
    {
    }
};

int main() {
    Base::Shared base;
    Derived::Shared derived; 
    MiniDerived::Shared md;
}
另一方面,我会坚持我现在的解决方案Frerich Raabe提到的。

3 个答案:

答案 0 :(得分:2)

您可以在Derived中明确指定要使用的Shared中的哪一个:

class Derived : public Base, public SmartAlias<Derived>
{
public:
    using Shared = SmartAlias<Derived>::Shared;
    // or in pre-C++11
    typedef SmartAlias<Derived>::Shared Shared;
};

这是另一个不需要向所有类添加typedef的选项。相反,它会修改在SmartAliasBase之间插入Derived的层次结构:

template <typename T, typename MyBase = void> class SmartAlias : public MyBase
{
public:
    typedef typename SmartAlias<T>::Shared Shared;
};

template <typename T> class SmartAlias<T, void> 
{
public:
    typedef QSharedPointer<T> Shared;
};

class Base : public SmartAlias<Base>
{
};

class Derived : public SmartAlias<Derived, Base>
{
};

答案 1 :(得分:2)

坦率地说,看到使用(公共)继承代码重用而不是接口重用的代码总是让我感到紧张。还有一个拥有&#39; Smart&#39;在它的名字几乎是一个代码味道给我。怎么样只是

class Base
{
public:
    typedef QSharedPointer<Base> Shared;
};

class Derived : public Base
{
public:
    typedef QSharedPointer<Derived> Shared;
};

答案 2 :(得分:0)

问题在于,当您创建Derived对象时,它将实际为Base创建一个对象,该对象将为SmartAlias创建一个对象,然后从Derived中有意地派生SmartAlias。因此,您为单个Derived对象提供了2个SmartAlias对象。当您想要使用Derived对象访问SmartAlias的成员时,肯定会导致模糊不清。因此,您无需将SmartAlias作为Derived的直接基础。