如何正确消除继承的 typedef 的歧义?以及如何缓解他们的创作?

How to correctly disambiguate inherited typedefs? And how to ease their creation?

让我们考虑一下我创建 Typedef class 以自动继承别名的代码。

#include <memory>

template <typename T>
struct Typedef
{
    typedef std::unique_ptr<T> Ptr;
    typedef std::unique_ptr<const T> ConstPtr;
};

struct X : public Typedef<X> { Ptr Func(); }; // no problem, Ptr = std::unique_ptr<X>
struct Y : public Typedef<Y> { Ptr Func(); }; // no problem, Ptr = std::unique_ptr<Y>

struct A : public X, public Typedef<A>
{
    using Typedef<A>::Ptr; // (A), better than typedef typename Typedef<A>::Ptr Ptr, am I right?
    Ptr Func();
};

struct B : public X, public Y, public Typedef<B>
{
    using Typedef<B>::Ptr; // (B)
    Ptr Func();
};

通常这没有问题,但是当我继承多个 classes 时,我必须消除多个继承别名之间的歧义。

  1. 有没有更简单的方法来消除歧义?(可能具有 C++14/17 特性)

  2. 如果没有,有没有更简单的方法自动为每个class创建别名?我不想在每个 class 定义中 typedef std::unique_ptr<Foo> Ptr 我希望在每个 class 中公开显示 Foo::PtrFoo::ConstPtr

  3. 最新的 Eclipse Oxygen 解析器坏了吗? 它通常能正确理解代码(包括 A),但突出显示 (B) 有错误:"typedef is ambiguous" .在这种情况下,原因似乎是多重继承。 GCC 没有问题,编译没有任何警告。

  4. 如果我的 Typedef class 声明了更多别名,并且我有冲突 - 有没有比 [=16= 更简单的方法来解决所有冲突], ...::ConstPtr 全部?

如果您真的坚持这种行为,一种可能是添加额外的 classes...

struct XBase { ... };
struct YBase { ... };

struct X : public XBase, public Typedef<X> { ... };
struct Y : public YBase, public Typedef<Y> { ... };

struct ABase { ... };
struct BBase { ... };

struct A : 
    public ABase, 
    public XBase, 
    public Typedef<A> { ... };

struct B : 
    public BBase, 
    public XBase, 
    public YBase, 
    public Typedef<B> { ... };

这样,每个 class 都有一种简单的方法来提供自己的别名,即使是多重继承也是如此。

但是,正如我在评论中所解释的那样,我通常不建议采用这种方法。

应避免多重 (public) 继承,因为它会产生强耦合。通常最好改用组合。 interface classes 是一个例外(只有纯虚函数,如果您打算能够从其接口指针销毁对象,则可能是虚析构函数)。混合可能是多重继承可能有用的另一种情况,但在这种情况下,您将使用私有继承,即使这样组合也可能更可取。耦合越少,如果您想进行重大更改,系统维护起来就越容易。

另外,正如我在评论中所解释的那样,定义此类 typedef 可能不是一个好主意,因为 std::unique_ptr<> 具有与之关联的行为,并且出于文档目的,您编写 std::unique_ptr<A> Func(); 可能会更好反正。它使函数的使用方式更加明显。