52 votes

appel à une fonction virtuelle pure à partir du constructeur de la classe de base

J'ai une classe de base MyBase qui contient une fonction virtuelle pure :

void PrintStartMessage() = 0

Je veux que chaque classe dérivée l'appelle dans son constructeur

puis je l'ai mis dans le constructeur de la classe de base ( MyBase )

  class MyBase
 {
 public:

      virtual void PrintStartMessage() =0;
      MyBase()
      {
           PrintStartMessage();
      }

 };

 class Derived:public MyBase
 {     

 public:
      void  PrintStartMessage(){

      }
 };

void main()
 {
      Derived derived;
 }

mais j'obtiens une erreur d'éditeur de liens.

  this is error message : 

 1>------ Build started: Project: s1, Configuration: Debug Win32 ------
 1>Compiling...
 1>s1.cpp
 1>Linking...
 1>s1.obj : error LNK2019: unresolved external symbol "public: virtual void __thiscall MyBase::PrintStartMessage(void)" (?PrintStartMessage@MyBase@@UAEXXZ) referenced in function "public: __thiscall MyBase::MyBase(void)" (??0MyBase@@QAE@XZ)
 1>C:\Users\Shmuelian\Documents\Visual Studio 2008\Projects\s1\Debug\s1.exe : fatal error LNK1120: 1 unresolved externals
 1>s1 - 2 error(s), 0 warning(s)

Je veux forcer toutes les classes dérivées à...

 A- implement it

B- call it in their constructor 

Comment dois-je faire ?

23voto

greatwolf Points 9561

Essayer d'appeler une méthode abstraite pure à partir d'un dérivé alors que cet objet est encore en cours de construction n'est pas sûr. C'est comme essayer de faire le plein d'essence dans une voiture, mais cette voiture est toujours sur la chaîne de montage et le réservoir d'essence n'a pas encore été mis en place.

Le plus proche possible de faire quelque chose comme ça est de construire d'abord complètement votre objet, puis d'appeler la méthode après :

 template <typename T>
T construct_and_print()
{
  T obj;
  obj.PrintStartMessage();

  return obj;
}

int main()
{
    Derived derived = construct_and_print<Derived>();
}

6voto

larsmans Points 167484

Vous ne devriez pas appeler une fonction virtual dans un constructeur. Période . Vous devrez trouver une solution de contournement, comme faire PrintStartMessage non virtual et placer l'appel explicitement dans chaque constructeur.

1voto

fatma.ekici Points 543

Si PrintStartMessage() n'était pas une fonction virtuelle pure mais une fonction virtuelle normale, le compilateur ne s'en plaindrait pas. Cependant, vous devrez toujours comprendre pourquoi la version dérivée de PrintStartMessage() n'est pas appelée.

Puisque la classe dérivée appelle le constructeur de la classe de base avant son propre constructeur, la classe dérivée se comporte comme la classe de base et appelle donc la fonction de la classe de base.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X