Peut-être encore mieux est: Pourquoi la norme nécessite-t-elle une transmission à une classe de base dans ces situations? (Ouais ouais ouais - Pourquoi - Parce que?.)Où dans la norme transmet à une classe de base requis dans ces situations?
class B1 {
public:
virtual void f()=0;
};
class B2 {
public:
virtual void f(){}
};
class D : public B1,public B2{
};
class D2 : public B1,public B2{
public:
using B2::f;
};
class D3 : public B1,public B2{
public:
void f(){
B2::f();
}
};
D d;
D2 d2;
D3 d3;
MS donne:
sourceFile.cpp
sourceFile.cpp(24) : error C2259: 'D' : cannot instantiate abstract class
due to following members:
'void B1::f(void)' : is abstract
sourceFile.cpp(6) : see declaration of 'B1::f'
sourceFile.cpp(25) : error C2259: 'D2' : cannot instantiate abstract class
due to following members:
'void B1::f(void)' : is abstract
sourceFile.cpp(6) : see declaration of 'B
et de même pour le compilateur MS.
I peut-être acheter le premier cas, D. Mais dans D2-f est sans ambiguïté défini par la déclaration using, pourquoi est-ce que cela ne suffit pas pour le compilateur d'être nécessaire pour remplir le vtable? Où dans la norme cette situation est-elle définie?
ajouté pour répondre à Reponse
En ce qui concerne la réponse ci-dessous que je l'ai accepté:
Pourquoi cela semble pas une erreur dans la spécification? - Si on a une hiérarchie d'héritage avec une série de f() non virtuels, dont l'utilisation dans les classes dérivées est déterminée en utilisant des instructions, et on change le decl de f dans une classe de base en virtual alors cela peut changer f est appelé dans les classes dérivées en utilisant des instructions pour choisir leur f. C'est un "gotcha" C++ dont je n'étais pas au courant. Cela peut faire partie de la langue, mais une telle «action à distance» me met mal à l'aise et me semble être une violation d'un principe d'exactitude/d'entretien (que je ne peux pas formuler tout à l'heure).
Mais je peux donner un exemple:
#include <iostream>
using std::cout;
namespace NonVirtual_f{
class C0 {
public:
void f(){cout<<"C0::f()"<<'\n';}
};
class C1 : public C0{
public:
void f(){cout<<"C1::f()"<<'\n';}
};
class C2 : public virtual C1{
public:
void f(){cout<<"C2::f()"<<'\n';}
};
class D3 : public virtual C1, public C2{
public:
using C1::f;
};
}//namespace NonVirtual_f
namespace Virtual_f{
class C0 {
public:
virtual void f(){cout<<"C0::f()"<<'\n';}
};
class C1 : public C0{
public:
void f(){cout<<"C1::f()"<<'\n';}
};
class C2 : public virtual C1{
public:
void f(){cout<<"C2::f()"<<'\n';}
};
class D3 : public virtual C1, public C2{
public:
using C1::f;
};
}//namespace Virtual_f
int main(int argc,const char* const*argv){
NonVirtual_f::D3 nv3;
nv3.f();
Virtual_f::D3 v3;
v3.f();
return 0;
}
D'où la sortie:
C1::f()
C2::f()
Tout ce qui est changé est la virtualité de f en C0. En particulier lorsque la non-virtualité de f dans une classe de base est choisie, elle ne peut pas être changée sans problèmes de maintenance si une classe dérivée (en général une classe ne peut pas) a été "surchargée" comme dans l'exemple immédiatement au-dessus.
Si vous contrez avec "Eh bien, ne surchargez pas de cette façon dans le cas NonVirtual", je suis d'accord c'est une mauvaise pratique mais cela semble plus que cela.Pour moi, la langue doit:
permettent pas l'utilisation de dans nonvirtual :: D3 (pas possible actuellement car il peut y avoir d'autres faire de surcharge f à [à moins d'utiliser autorisés une signature dans le cas de la fonction])
ou
refuser l'aide d'instructions de fonctions complètement et la force d'envoi
ou
avoir l'aide passer outre en fait dans tous les cas
ou
permettent à certaines déclarative pour les fonctions syntaxiques (essentiellement une fonction à l'aide) comme:
void f(*signature*) = C2::f;
Qu'est-ce, exactement, suis-je manque ici? Quelqu'un peut-il proposer un scénario qui clarifie le «pourquoi» de ce choix dans la norme?
Pour votre information: les erreurs sont affichées à partir de Visual C++ :-) –
EDG "sourceFile.cpp", ligne 24: Erreur: objet du type de classe abstraite "D" n'est pas autorisé: la fonction virtuelle pure "B1 :: f" n'a pas de priorité D d; ^ "sourceFile.cpp", ligne 25: erreur: objet de type abstrait de classe "D2" est interdite: fonction virtuelle pure "B1 :: f" n'a pas de crosse D2 d2; ^ – pgast
Vous le savez peut-être déjà, mais juste en tant que FYI, si vous aviez mis f() = 0 dans une classe de base virtuelle de B1 et B2, alors D fonctionnerait. Voir la délégation de la classe soeur: http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.10 –