C ++: Derived + Base de classe implémenter une seule interface?
En C++, est-il possible d'avoir une base plus classe dérivée de mettre en œuvre une interface unique?
Par exemple:
class Interface
{
public:
virtual void BaseFunction() = 0;
virtual void DerivedFunction() = 0;
};
class Base
{
public:
virtual void BaseFunction(){}
};
class Derived : public Base, public Interface
{
public:
void DerivedFunction(){}
};
void main()
{
Derived derived;
}
Cela échoue, car Dérivé ne peut pas être instanciée. Aussi loin que le compilateur est concerné Interface::BaseFunction n'est jamais défini.
Jusqu'à présent la seule solution que j'ai trouvé serait de déclarer un passage à travers la fonction de Dérivées
class Derived : public Base, public Interface
{
public:
void DerivedFunction(){}
void BaseFunction(){ Base::BaseFunction(); }
};
Est-il une meilleure solution?
EDIT: Si c'est important, ici, c'est un réel problème que j'ai eu l'aide de MFC boîtes de dialogue.
J'ai une classe de boîte de dialogue (MyDialog permet de dire) dérivée de CDialog. En raison de problèmes de dépendance, j'ai besoin de créer une interface abstraite (MyDialogInterface). La classe qui l'utilise MyDialogInterface doit utiliser les méthodes spécifiques à MyDialog, mais aussi des besoins à l'appel de CDialog::SetParent. Je viens de résoudre par la création de MyDialog::SetParent et en la faisant passer à travers CDialog::SetParent, mais je me demandais si il y avait une meilleure façon.
source d'informationauteur Joe
Vous devez vous connecter pour publier un commentaire.
C++ n'est pas l'avis de la fonction héritée de Base implémente déjà
BaseFunction
: La fonction doit être mis en œuvre de manière explicite dans une classe dérivée deInterface
. Le changement de cette façon:Si vous voulez être en mesure de s'en tirer avec seulement la mise en œuvre de l'un d'eux, split
Interface
en deux interfaces:Remarque: la main doit retourner int
Remarque: il est de bonne pratique de garder
virtual
en face de fonctions de membre dans les dérivés qui ont été virtuel dans la base, même si cela n'est pas strictement nécessaire.On dirait qu'il n'est pas tout à fait le cas que "Dérivée" est-un" de Base, ce qui suggère que le confinement peut être une meilleure mise en œuvre de l'héritage.
Aussi, votre Dérivées des fonctions de membre doit être decalred virtuelle en tant que bien.
Vous pouvez rendre le contenu de membre d'une référence ou un pointeur intelligent, si vous voulez cacher les détails d'implémentation.
Le problème est que, dans votre exemple, vous avez deux implémentations de
Interface
l'un venant deBase
et celle venant deDerived
. C'est par la conception dans le langage C++. Comme l'a déjà souligné, il suffit de retirer leInterface
classe de base sur la définition deDerived
.Je suis d'accord avec la réponse par des litb. Cependant, il y a ici l'occasion de comprendre quelque chose de la façon dont les fonctions virtuelles et l'héritage multiple travail.
Lorsqu'une classe a plusieurs classes de base, il a séparé les vtables pour chaque classe de base.
Derived
aura une vtable structure qui ressemble à ceci:En outre, chaque classe de base ne pourra voir sa propre vtable. Lorsque
Base
est instancié, il remplit dans leBase::BaseFunction
pointeur dans la vtable, mais ne peut pas voir la vtable pour l'Interface.Si le code que vous avez fourni pourrait compiler, la vtable de la structure d'une instance de
Derived
devrait ressembler à ceci:J'en ai trouvé une chose qui manque de litb de réponse. Si j'ai un
Derived
exemple, je peux obtenir unDerivedInterface
etBaseInterface
. Mais si je n'ai qu'unDerivedInterface
je ne peux pas obtenir unBaseInterface
depuis découlantDerivedInterface
deBaseInterface
ne fonctionne pas.Mais, tout ce temps j'ai été de limiter moi-même au moment de la compilation, de vérification pour une raison quelconque. Cette
DerivedInterface
fonctionne tout simplement génial:Pas de passer à travers les fonctions nécessaires dans la Dérivée, et tout le monde est heureux. Bien sûr, il n'est pas strictement une interface plus, mais c'est très bien. Pourquoi n'ai-je pas penser à cela plus tôt? 🙂