【问题标题】:Unable to call base constructor in template class using virtual inheritance无法使用虚拟继承在模板类中调用基本构造函数
【发布时间】:2015-03-27 10:16:43
【问题描述】:

this question相关;下面的代码试图隐藏每个特定组件实现的公共构造函数,同时在每个组件上提供一个通用的create 函数(它的实现总是做同样的事情:通过管道与服务器通信)。

通过使用多重继承,我试图向需要访问组件字段的组件添加功能。由于我只希望每个组件中有一个 g_component 实例,因此我使用虚拟继承。

g_component 类如下所示:

class g_component {
protected:
    uint32_t id;

    g_component(uint32_t id) :
            id(id) {
    }

    template<typename T>
    class g_concrete: virtual T {
    public:
        g_concrete(uint32_t id) :
                T(id) { // <----------- this fails compilation
        }
    };

    template<typename COMPONENT_TYPE, uint32_t COMPONENT_CONSTANT>
    static COMPONENT_TYPE* createComponent() {
        // write request: using the COMPONENT_CONSTANT
        // read response: component_id is read from the response
        if (response_successful) {
            return new g_concrete<COMPONENT_TYPE>(component_id);
        }
        return 0;
    }
};

然后是可以有标题的g_titled_component

class g_titled_component: virtual public g_component {
public:
    g_titled_component(uint32_t id) :
            g_component(id) {
    }

    virtual ~g_titled_component() {
    }

    virtual void setTitle(std::string title) {
        // this implementation must have access to g_component::id
    }
};

最后,g_button 及其实现如下所示:

class g_button: virtual public g_component, virtual public g_titled_component {
protected:
    g_button(uint32_t id) :
            g_component(id), g_titled_component(id) {
    }
public:
    static g_button* create();
};

g_button* g_button::create() {
    return createComponent<g_button, G_UI_COMPONENT_BUTTON>();
}

这样应该没问题,因为通过虚继承,g_component的构造函数只会被调用一次。问题是,在g_concrete的构造函数中调用父构造函数时编译失败:

In file included from src/ui/button.hpp:13:0,
                 from src/ui/button.cpp:12:
src/ui/component.hpp: In instantiation of 'static COMPONENT_TYPE* g_component::createComponent() [with COMPONENT_TYPE = g_button; unsigned int COMPONENT_CONSTANT = 0u]':
src/ui/button.cpp:18:58:   required from here
src/ui/component.hpp:71:54: error: 'g_button' is an inaccessible base of 'g_component::g_concrete<g_button>'
    return new g_concrete<COMPONENT_TYPE>(component_id);
                                                      ^
src/ui/component.hpp: In instantiation of 'g_component::g_concrete<T>::g_concrete(uint32_t) [with T = g_button; uint32_t = unsigned int]':
src/ui/component.hpp:71:54:   required from 'static COMPONENT_TYPE* g_component::createComponent() [with COMPONENT_TYPE = g_button; unsigned int COMPONENT_CONSTANT = 0u]'
src/ui/button.cpp:18:58:   required from here
src/ui/component.hpp:38:9: error: no matching function for call to 'g_component::g_component()'
     T(id) {
         ^
src/ui/component.hpp:38:9: note: candidates are:
src/ui/component.hpp:27:2: note: g_component::g_component(uint32_t)
  g_component(uint32_t id) :
  ^
src/ui/component.hpp:27:2: note:   candidate expects 1 argument, 0 provided
src/ui/component.hpp:23:7: note: constexpr g_component::g_component(const g_component&)
 class g_component {
       ^
src/ui/component.hpp:23:7: note:   candidate expects 1 argument, 0 provided
src/ui/component.hpp:23:7: note: constexpr g_component::g_component(g_component&&)
src/ui/component.hpp:23:7: note:   candidate expects 1 argument, 0 provided
src/ui/component.hpp:38:9: error: no matching function for call to 'g_titled_component::g_titled_component()'
     T(id) {
         ^
src/ui/component.hpp:38:9: note: candidates are:
In file included from src/ui/button.hpp:14:0,
                 from src/ui/button.cpp:12:
src/ui/titled_component.hpp:30:2: note: g_titled_component::g_titled_component(uint32_t)
  g_titled_component(uint32_t id) :
  ^
src/ui/titled_component.hpp:30:2: note:   candidate expects 1 argument, 0 provided
src/ui/titled_component.hpp:22:7: note: g_titled_component::g_titled_component(const g_titled_component&)
 class g_titled_component: virtual public g_component {
       ^
src/ui/titled_component.hpp:22:7: note:   candidate expects 1 argument, 0 provided

为什么这不起作用? g_concrete的虚继承不应该调用g_button的ctor,导致g_component的ctor被调用吗?

【问题讨论】:

    标签: c++ templates inheritance virtual-inheritance


    【解决方案1】:

    你总是需要构造 virtual 基,即使是间接的。

    你不是。

    特别是g_concrete&lt;g_button&gt;: g_button: virtual g_componentg_concrete 的 ctor 构造了 g_button,但构造失败了 g_component。不,您不能将此任务委托给g_button:这就是virtual 继承的代价。

    这些错误消息令人困惑,因为g_concrete 既是封闭类又是间接基类。

    您为什么要做virtual 继承尚不清楚。

    【讨论】:

    • 我需要使用virtual继承,因为我想拥有多种类型的组件(比如g_titled_componentg_colored_componentg_bounded_component),我可以使用它们来扩展一个子类而不重新实现它。
    • @maxdev 最简单的解决方案是将i_component 与您虚拟继承的virtual int get_id() = 0 结合使用。然后在最终类中,您从实现i_componentx_component 非虚拟继承。这有抽象的惩罚,但是因为您实际上只从抽象类继承,所以消除了构造问题。另一种方法是使用基于模板的线性继承,您将父类型传递给每个。我从你的设计中不确定为什么 setTitlevirtual 作为旁白。
    【解决方案2】:

    代码

    g_button* g_button::create() {
    return createComponent<g_button, G_UI_COMPONENT_BUTTON>();
    }
    

    正在从g_concrete&lt;g_button&gt;* 转换为g_button*,而g_buttong_concrete&lt;g_button&gt; 的私有不可访问基础,因为class g_concrete: virtual T

    因此,请尝试将 class g_concrete: virtual T { 更改为 class g_concrete: public virtual T {

    【讨论】:

    • 没有区别,因为g_concrete 是在g_button 中定义的。也不行。
    猜你喜欢
    • 2013-10-24
    • 1970-01-01
    • 2021-04-20
    • 1970-01-01
    • 2018-03-31
    • 2015-06-21
    • 1970-01-01
    • 1970-01-01
    • 2020-03-10
    相关资源
    最近更新 更多