En relation avec this question; le code suivant tente de cacher les constructeurs publics de chaque implémentation de composant spécifique tout en fournissant une fonction générique create
sur chaque composant (l'implémentation de celui-ci fait toujours la même chose: communiquer via un canal avec un serveur). En utilisant l'héritage multiple j'essaye d'ajouter la fonctionnalité aux composants qui doivent accéder aux champs de composants. Comme je ne veux qu'une instance de g_component
dans chaque composant, j'utilise l'héritage virtuel.Impossible d'appeler le constructeur de base dans la classe modèle à l'aide de l'héritage virtuel
La classe ressemble g_component
ceci:
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;
}
};
Ensuite, il y a le g_titled_component
qui peut avoir un titre:
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
}
};
Enfin, le g_button
et sa mise en œuvre se présentent comme suit:
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>();
}
Cela devrait être bon, comme Par l'héritage virtuel, le constructeur de g_component
ne sera appelé qu'une seule fois. Le problème est que la compilation échoue où le constructeur parent est appelé dans le constructeur de 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
Pourquoi ça marche pas? L'héritage virtuel de g_concrete
ne devrait-il pas appeler le ctor de g_button
, entraînant l'appel du ctor de g_component
?
Cela ne fait aucune différence puisque 'g_concrete' est défini dans' g_button'. Ne fonctionne pas non plus. – maxdev