Frage

Ich lerne immer noch C ++; Ich habe versucht, wie Polymorphismus funktioniert und ich einen Segmentation Fault bekam, wenn eine virtuelle Methode aufrufen.

(Anmerkung: Ich habe nicht die destructor als virtuelle markieren, ich habe nur versucht, um zu sehen, was passiert.) Hier ist der 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();
}

Auch wenn Sie andere Tipps haben für jemanden die Verwendung von Vererbung und Polymorphismus im Allgemeinen in Bezug auf die diese Konzepte in Java kennt, lassen Sie es mich wissen. Vielen Dank!

War es hilfreich?

Lösung

Name - wird unintialized in Basis

Sie auch ein anderes Problem haben:

  Base c = Child("2");

Ich glaube nicht, es ist das, was Sie wollen. Ihr Code wird eine Instanz von Basis aus gegossenem Child erstellen. Aber ich denke, Sie mit dem Kind Instanz arbeiten möchten, basierend auf Base-Schnittstelle; Sie sollten stattdessen schreiben:

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

auch, um zu verhindern zukünftige Fehler, erklärt destructor in der Basis als virtuell.

Andere Tipps

Sie initialisieren nie die Basis nenber Variable - Ihr Basiskonstruktor sein sollte:

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

Sowie, dass, wenn Sie sagen,

Base b = Child( "xxx" );

dann wird das Kind beispielsweise in Scheiben geschnitten werden, um eine Basis nach unten, das ist wahrscheinlich nicht das, was Sie wollen.

Ich glaube nicht, dass Sie das Element char * Namen in Ihrem ctors zu etwas sind zuweisen.

Das Kind :: disp () -Methode wird nie genannt werden. - c eine Variable vom Typ Base, und nicht ein Zeiger oder eine Referenz, so dass es nicht für virtuelle Methoden überprüfen wird

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

nennen würde Child :: disp ().

Whoa es.

Es gibt ein paar Probleme, aber Ihr segfault ist wahrscheinlich, weil Sie eine char* vorbei sind - das ist nur ein Zeiger ist, und dann versuchen, es in cout disp(). Problem ist, wird der Zeiger nicht in disp() lebt, sie lebt in main(). Sie wollen wahrscheinlich die char* entweder tief kopieren oder std::string verwenden. es auf diese Weise tun, wird nicht funktionieren.

Bearbeiten :

Siehe EDIT 2

Sie können nicht nur zuweisen Namen der name Variable Klasse. Wenn Sie das tun, werden Sie unvorhersehbare Ergebnisse erhalten - und Sie werden wahrscheinlich noch segfault. Denken Sie daran: in C / C ++, Objekte werden lokal, es sei denn auf dem Heap zugewiesen scoped. In diesem Fall in Ihrem Ctor, würden Sie so etwas wie zu tun:

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

Und in dem destructor, werden Sie wie etwas tun:

delete [] this->name;

Hinweis: meine Syntax völlig falsch sein kann, und ich merke, der obige Code von Natur aus unsicher ist, wie Sie nicht die char* Überprüfung sicherstellen, dass es nicht NULL ist, und Sie nicht den Rückgabewert von new. Überprüfung Dennoch ist diese erhalten sollten Sie begonnen haben.

EDIT 2: Ich stehe korrigiert. Stringliterale werden als konstante Lagerung behandelt und damit leben für die Dauer des Programms. Dennoch , die Lektion, glaube ich, ist wichtig: im allgemeinen, wenn nicht mit Stringliterale Umgang , indem ein Zeiger (oder Array, etc.), müssen Sie zuzuteilen Lagerung für sie und Tief Kopie. Sie müssen auch entsprechend de-zuteilen, wenn das Objekt zerstört wird.

Es gibt nur wenige Probleme. Das erste, was ist Ihre Basisklasse Destruktor virtuell sein muss. Andernfalls wird Ihre destructor Basisklasse wird immer noch genannt werden, wenn es auf abgeleitete Objekt zeigt. Zweitens ist es, Sie sollten nicht abgeleiteten Klasse Objekt Basisklasse Objekt zuordnen. Dies wird Gegenstand Slicing bezeichnet. So Zuordnung sollte durch Zeiger oder eine Referenz durchgeführt werden.

Die Segmentierung Problem geschieht, weil es Müll Wert enthält. Sie müssen es in den Konstruktor initialisieren.

Sie haben ein paar Probleme mit Ihrem Code.

Zuerst, und der Grund, warum Sie einen segfault bekommt, ist die Umsetzung des Base-Ctor einen Parameter mit dem gleichen Namen wie eine der Klasse Membervariablen nimmt:

class Base
{
protected:
  char *name;

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

Der Ctor des Parameter 'name' versteckt das Klasse Membervariable von den gleichen, erm ... Namen.

Zweitens sind Sie Slicing Ihr Objekt hier:

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

‚c‘ ist vom Typ Base und Sie versuchen, ein Kind zu ihm zuweisen. All die Dinge, die einzigartig für Kind ist wird abgeschnitten, wenn Sie die ogbject auf die Basisklasse zugeordnet werden.

Hier ist Code, der beide diese Probleme behebt:

#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;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top