Frage

Ich habe drei verschiedene Basisklassen:

class BaseA
{
public:
    virtual int foo() = 0;
};

class BaseB
{
public:
    virtual int foo() { return 42; }
};

class BaseC
{
public:
    int foo() { return 42; }
};

I ableiten dann von der Basis so (Ersatz X für A, B oder C):

class Child : public BaseX
{
public:
    int foo() { return 42; }
};

Wie wird die Funktion in den drei verschiedenen Basisklassen außer Kraft gesetzt? Sind meine drei folgenden Annahmen korrekt? Gibt es noch andere Vorbehalte?

  • Mit BaseA, wird das Kind Klasse nicht kompilieren, die rein virtuelle Funktion nicht definiert ist.
  • Mit Baseb, die Funktion in dem Kind genannt wird, wenn es auf einem Baseb Aufruf foo * oder Kind *.
  • Mit BASEC, die Funktion in dem Kind aufgerufen wird, wenn foo auf Kinder Aufruf * aber nicht auf Baseb * (die Funktion in Elternklasse genannt wird).
War es hilfreich?

Lösung

In der abgeleiteten Klasse eine Methode ist virtuell, wenn es in der Basisklasse virtuell definiert ist, auch wenn das Schlüsselwort virtual nicht in der abgeleiteten Klasse-Methode verwendet wird.

  • Mit BaseA, wird es kompilieren und ausführen, wie beabsichtigt, mit foo() virtuell ist und in der Klasse Child ausgeführt wird.
  • Samt mit BaseB, wird es auch wie beabsichtigt kompilieren und ausführen, mit foo() virtuellen Wesen () und in der Klasse Child ausgeführt wird.
  • Mit BaseC wird es jedoch kompilieren und ausführen, aber es wird die BaseC Version ausführen, wenn Sie es aus dem Kontext der BaseC nennen, und die Child Version, wenn Sie mit dem Kontext von Child nennen.

Andere Tipps

Die wichtige Regel zu erinnern ist, sobald eine Funktion virtuelle deklariert wird, Funktionen mit Signaturen in den abgeleiteten Klassen Anpassung immer virtuell sind. So ist es für Kinder von A und Kind von B außer Kraft gesetzt, die identisch verhalten würden (mit Ausnahme von Ihnen nicht direkt BaseA instanziiert).

Mit C, jedoch ist die Funktion nicht außer Kraft gesetzt, sondern überlastet. In dieser Situation wird nur die statische Typ Angelegenheiten: wird es nennt es, was es ist ein Zeiger auf (vom statischen Typ) statt, was das Objekt wirklich ist (der dynamische Typ)

  

Mit BaseA, tut das Kind Klasse nicht   kompilieren, die rein virtuelle Funktion   ist nicht definiert

Dies gilt allerdings nur, wenn Sie versuchen, ein Objekt von BaseA zu erstellen. Wenn Sie ein Objekt des Kindes erstellen und dann können Sie rufen foo () entweder BaseA * oder Kind *

  

Mit Baseb, die Funktion in dem Kind   aufgerufen wird, wenn foo auf einem Baseb Aufruf *   oder Kind *.

Abhängig von der Art des Objekts, wenn das Objekt entweder Baseb oder Kind sein kann. Wenn das Objekt Baseb dann Baseb :: foo aufgerufen.

  

Mit BASEC, TheFunction im Kind   aufgerufen wird, wenn foo auf Kinder Aufruf *   aber nicht auf Baseb * (die Funktion in   Elternklasse genannt wird).

Ja, aber Sie wollen nicht, dies zu tun.

Von einem Polymorphismus Sicht bevorzugen A, so dass Sie jedes Kind wissen, hat seine eigene Implementierung der virtuellen Funktion.
Wählen Sie B vor allem wenn Sie eine gültige Standardimplementierung haben, aber dann müssen Sie sicherstellen, dass alle Kind-Klassen ihre eigene Implementierung haben je nach Bedarf. C ist nicht Polymorphismus, so umsichtig verwenden.

Es hängt vor allem davon ab, wie Sie es genannt.

Wenn Sie getan haben:

class Child : public BaseA
{
public:
    int foo() { return 42; }
};

und tat

BaseA baseA = new Child();
baseA->foo();

Es würde nennen Kinder foo Funktion.

Wenn Sie jedoch tun dies:

BaseA baseA = new BaseA();

Es wäre eine Kompilierung Fehler.

Klasse Child wird , wenn von A abgeleitet kompilieren, kann man einfach nicht Objekte dieses Typs instanziiert.

Dies könnte nützlich sein, wenn Sie einige Funktionen von Base zu überschreiben werden, und dann wieder abzuleiten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top