Связано с 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>();
}
Это должно быть хорошо, поскольку ugh виртуальное наследование, конструктор 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
вызвать ctor g_button
, в результате чего получится вызов ctor g_component
?
Не имеет значения, поскольку 'g_concrete' определен в' g_button'. Не работает. – maxdev