【问题标题】:How to deal with ambiguities in same template multiple inheritance?如何处理同一模板多重继承中的歧义?
【发布时间】:2015-04-20 18:27:32
【问题描述】:

我正在开发自己的 WinAPI 包装库,它负责处理与 GUI 相关的所有内容。我在 Android 平台上看到了一些移植的解决方案(视图、测量/布局/绘制通道、从 XML 中“膨胀”UI)。

现在:我不想重复自己并手动添加静态方法,例如 create 和 inflate 到每个 ViewButtonGridViewTextView 等)。

基类View 派生自(将 View 作为 T 传递):

template<class T>
class ICreatable : std::enable_shared_from_this<T> {
public:
    static std::shared_ptr<T> create() {
        return std::shared_ptr<T>(new T()); //assume that T has such constructor
    }
    static std::shared_ptr<T> inflate(AttributeSet* attrs) {
        return std::shared_ptr<T>(new T(attrs)); //assume that T has such constructor
    }
    std::shared_ptr<T> ptr() {
        return enable_shared_from_this::shared_from_this();
    }
};

子类派生自 View 和 ICreatable:

class Button : public View, public ICreatable<Button> {
    //...
}

现在我必须以某种方式处理歧义 - Button 具有 ICreatable 并且 View 和 Button 都作为 T 传递。我希望 ButtonICreatable&lt;Button&gt; 覆盖 ICreatable&lt;View&gt;

  • 这在 C++ 中是否可行?
  • 如果没有,是否有其他方法 实现这种“自动静态方法添加”?
  • 我应该 回到我手动添加静态的第一个(可怕的)想法 每个 View 的 create() 和 inflate() 方法?

编辑: 经过一番讨论,我提出了一种#define 将这些方法缩短为一行的方法:

#define InsertCreatableMethods(T) \
static std::shared_ptr<T> create() {\
return std::shared_ptr<T>(new T());\
}\
static std::shared_ptr<T> inflate(AttributeSet* attrs) {\
    return std::shared_ptr<T>(new T(attrs));\
}
//...
class Button : public View {
    //...
public:
    InsertCreatableMethods(Button)
    //...
}

上面的代码是实现我想要的最好的方式(嗯,我认为是最懒惰的方式)。

【问题讨论】:

  • 为什么你希望同一个类既是 ICreatable 又是 ICreatable
  • 我希望每个 View 类只有一个 ICreatable(具有“最新”类为 T),但由于某些 View 派生自其他 View,ICreatable 也与它们一起派生。
  • 不,视图不是抽象的。这里还有更长的“继承链”。例如:ICreatable->View->ViewGroup(+ICreatable)->LinearLayout(+ICreatable)
  • 你为什么需要所有shared_from_this的东西?
  • 我在某处使用它。最初它位于 View 类中(并且 ptr() 返回 shared_ptr 可以动态转换为派生类...

标签: c++ multiple-inheritance class-template


【解决方案1】:

如果你写IView如下:

template <class T>
class View : public ICreatable<T>

你可以把按钮写成:

template <class T>
class Button : public View<T>

并且不需要双重继承。 如果你还有一个

class RadioButton : public Button<RadioButton>

一般来说,拥有深度继承树并不是好的设计。中间叶子应该是抽象的。 Button 没有具体含义。只有RadioButton 可以。更好的设计应该是这样的:

template <class T>
class IView : public ICreatable<T>

class View : public IView<View>

template <class T>
class IButton : public IView<T>

class Button : public IButton<Button>

这种方式没有双重继承,每个类都有一个简单的继承树。

【讨论】:

  • 这是我的第一个想法,但现在任何 View 都可以从另一个派生,如果我想用另一个 ICreatable 创建 LinearLayout,那么使用带有 ICreatable 的 ViewGroup 的好处将会丢失.当然,我可以创建具有final ViewGroupILinearLayout 的IViewGroup 和final LinearLayout
  • 让你所有的班级都添加那个小的template &lt;class T&gt;样板,然后你的整个结构就可以工作了。我认为您并不真正想要多重继承,因为实际上只有一种方法可以创建每个类。
  • 好吧,我做了这个 ICreatable 因为我很懒,而且我讨厌重复同样的事情很多次(这是浪费时间)。而且我认为为每个类使用一种丑陋的定义比通过添加模板(应该包含所有代码)来重构所有内容更容易。
  • 你最终将所有库都放在头文件中。那将是地狱
  • 最好的方法是有一个正常的类层次结构。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-12
  • 1970-01-01
  • 2018-05-23
  • 2011-02-09
  • 2016-05-07
相关资源
最近更新 更多