与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被调用吗?
答案 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_component
。 g_concrete
的ctor构造g_button
,但未能构建g_component
。不,您可以不将此任务委托给g_button
:这是virtual
继承的价格。
错误消息令人困惑,因为g_concrete
既是封闭类又是间接基础。
为什么你做virtual
继承不明确。