无法使用虚拟继承在模板类中调用基础构造函数

时间:2015-03-27 10:16:44

标签: c++ templates inheritance virtual-inheritance

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被调用吗?

2 个答案:

答案 0 :(得分:0)

代码

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

g_concrete<g_button>*投射到g_button*g_button由于g_concrete<g_button>而成为class g_concrete: virtual T的私人无法访问的基地。

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

答案 1 :(得分:0)

你总是需要构建virtual个基础,甚至是间接的基础。

你不是。

特别是g_concrete<g_button>: g_button: virtual g_componentg_concrete的ctor构造g_button,但未能构建g_component。不,您可以不将此任务委托给g_button:这是virtual继承的价格。

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

为什么你做virtual继承不明确。