Question

J'apprends encore C ++; Je tentais comment fonctionne le polymorphisme et je suis une erreur de segmentation lors de l'appel d'une méthode virtuelle.

(Note: Je ne marque pas la destructor comme virtuelle, je viens d'essayer de voir ce qui se passe.) Voici le code:

#include <iostream>

using namespace std;

class Base
{
protected:
  char *name;

public:
  Base(char *name)
  {
    cout << name << ": Base class cons" << endl;
  }

  ~Base()
  {
    cout << name << ": Base class des" << endl;
  }

  virtual void disp();
};

void Base::disp()
{
  cout << name << ": Base disp()" << endl;
}

class Child : public Base
{
public:
  Child(char *name):
    Base(name)
  {
    cout << name << ": Child class cons" << endl;
  }

  ~Child()
  {
    cout << name << ": Child class des" << endl;
  }

  virtual void disp()
  {
    cout << name << ": Child disp()" << endl;
  }
};


int main()
{
  //Base b;
  //b.disp();
  Base c = Child("2");
  c.disp();
}

En outre, si vous avez d'autres conseils concernant l'utilisation de l'héritage et le polymorphisme en général pour quelqu'un qui connaît ces concepts en Java, s'il vous plaît laissez-moi savoir. Merci!

Était-ce utile?

La solution

nom - est unintialized dans la base

aussi vous avez un autre problème:

  Base c = Child("2");

Je ne pense pas que ce soit ce que vous voulez. Votre code va créer une instance de base de l'enfant casted. Mais je pense que vous voulez travailler avec l'instance de l'enfant basé sur l'interface de base; vous devriez plutôt écrire:

  Base *c = new Child("2");

aussi, pour éviter les bugs futurs, déclarer destructor dans la base comme virtuelle.

Autres conseils

Vous n'initialisez la variable base nenber - votre constructeur de base devrait être:

Base(char * aname) : name( aname )
  {
    cout << name << ": Base class cons" << endl;
  }

En plus de cela, quand vous dites

Base b = Child( "xxx" );

alors l'instance de l'enfant sera coupé en tranches jusqu'à une base, ce qui est sans doute pas ce que vous voulez.

Je ne pense pas que vous affectez le membre omble chevalier * nom à quoi que ce soit dans votre cteurs.

L'enfant :: méthode AFF () ne sera jamais appelé -. C est une variable de type base, et non un pointeur ou une référence, il ne vérifie pas les méthodes virtuelles

Base * c = new Child("1");
c->disp();
delete c;

appellerait enfant :: AFF ().

Whoa là.

Il y a quelques problèmes, mais votre segfault est probablement parce que vous passez un char* - qui est juste un pointeur, puis essayer de cout dans disp(). Le problème est que le pointeur ne vit pas dans disp(), il vit dans main(). Vous voulez probablement soit de copie en profondeur la char*, ou utilisez std::string. En procédant ainsi, ne fonctionnera pas.

EDIT :

Voir EDIT 2

Vous ne pouvez pas simplement attribuer un nom à la variable name de la classe. Si vous faites cela, vous obtiendrez des résultats imprévisibles - et vous aurez probablement encore Segfault. Rappelez-vous: en C / C ++, les objets sont scope localement moins affecté sur le tas. Dans ce cas, dans votre cteur, vous voulez faire quelque chose comme:

this->name = new char[ strlen( name ) + 1 ];
strcpy( this->name, name );

Et dans le destructor, vous aurez envie de faire quelque chose comme:

delete [] this->name;

Remarque: ma syntaxe peut être complètement faux, et je me rends compte du code ci-dessus est intrinsèquement dangereux que vous n'êtes pas vérifier la char* pour vous assurer qu'il est pas NULL, et vous n'êtes pas vérifier la valeur de retour de new. Néanmoins, cette si vous commencer.

EDIT 2: Je me suis trompé. Les littéraux de chaîne sont traités comme stockage constant et vivent ainsi pendant toute la durée du programme. Néanmoins , la leçon, je crois, est importante: en général, quand ne pas traiter avec des chaînes littérales , en passant un pointeur (ou un tableau, etc.), vous devez allouer stockage pour et copie en profondeur. Vous devez également désallouer de façon appropriée lors de la destruction dudit objet.

Il y a quelques problèmes ici. La première chose est votre destructor de classe de base doit être virtuelle. Sinon, votre classe de base destructor sera toujours appelée même si elle pointe vers objet dérivé. Deuxièmement, vous ne devriez pas affecter objet de classe dérivée à l'objet de classe de base. Ceci est appelé découpage en tranches d'objet. Ainsi, la cession doit se faire par pointeur ou de référence.

Le problème de segmentation se produit car il contient la valeur des déchets. Vous devez l'initialiser dans le constructeur.

Vous avez quelques problèmes avec votre code.

D'abord, et la raison pour laquelle votre obtenir un segfault, est la mise en œuvre de la cteur de base prend un paramètre du même nom que l'une des classes variables membres:

class Base
{
protected:
  char *name;

public:
  Base(char ***name**)
  {
    cout << name << ": Base class cons" << endl;
  }

'nom' paramètre du cteur cache la variable membre de classe du même, erm ... nom.

En second lieu, vous tranchage votre objet ici:

int main()
{
  //Base b;
  //b.disp();
  Base c = Child("2");
  c.disp();
}

« c » est de type base, et que vous essayez d'assigner un enfant à elle. Toutes les choses qui est unique à l'enfant sera trancha lorsque vous attribuez la ogbject à la classe de base.

Voici le code qui fixe ces deux problèmes:

#include <iostream>
#include <string>

using namespace std;

class Base
{
protected:
    std::string name_;

public:
  Base(char *name)
      : name_(name) {
    cout << name_ << ": Base class cons" << endl;
  }

  ~Base()
  {
    cout << name_ << ": Base class des" << endl;
  }

  virtual void disp();
};

void Base::disp()
{
  cout << name_ << ": Base disp()" << endl;
}

class Child : public Base
{
public:
  Child(char *name):
    Base(name)
  {
    cout << name_ << ": Child class cons" << endl;
  }

  ~Child()
  {
    cout << name_ << ": Child class des" << endl;
  }

  virtual void disp()
  {
    cout << name_ << ": Child disp()" << endl;
  }
};


int main()
{
  //Base b;
  //b.disp();
  Base * c = new Child("2");
  c->disp();
  delete c;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top