7 Stimmen

Soll eine using-Deklaration eine geerbte virtuelle Funktion verbergen?

struct level0
{
  virtual void foo() = 0;
};

struct level1 : level0
{
  virtual void foo() { cout <<" level1  " << endl; }
};

struct level2 : level1
{
  virtual void foo() { cout <<" level2 " << endl; }
};

struct level3 : level2
{
  using level1::foo;
};

int main()
{
  level1* l1 = new level3;
  l1->foo();
  level3 l3;
  l3.foo();
  return 0;
}

der obige Code mit gcc ergibt

level2
level1

aber in icc gibt

 level2
 level2

Welches ist richtig, oder ist es in der Norm nicht definiert?

Bearbeiten: Dies beweist, dass es sich um einen Fehler handelt, betrachten Sie die folgende Hauptfunktion

int main()
{
    level3 l3;
    l3.foo();               // This prints level1

    level3* pl3 = &l3;
    pl3->foo();             // This prints level2

    level3& rl3 = l3;
    rl3.foo();              // This prints level1

    level3& rpl3 = *pl3;
    rpl3.foo();             // This prints level2

    return 0;
}

Also das gleiche Objekt, wenn direkt verwendet produziert unterschiedliche Ergebnisse und wenn über einen Zeiger des gleichen Typs verwendet produziert unterschiedliche Ergebnisse!!!

0 Stimmen

Ich würde vermuten, dass GCC richtig ist, aber ich bin mir nicht sicher.

0 Stimmen

Ich habe das Verhalten mit TDM MinGW g++ 4.4.1 bestätigt. Es ist ein G++-Fehler, bitte melden Sie ihn. Prost & hth.,

0 Stimmen

Komisch, ich habe mir das erst gestern angesehen.

5voto

aschepler Punkte 68538

Ein Beispiel im Standardabschnitt 10.3p2 macht deutlich, dass die Verwendung von Deklarationen no virtuelle Funktionen außer Kraft setzen.

Dies ist eine bekannter G++-Fehler .

Wie Sie bemerkt haben, tritt der Fehler nicht auf, wenn die Mitgliedsfunktion über eine Referenz oder einen Zeiger aufgerufen wird, und nicht in einem Fall, in dem der dynamische Typ bekannt ist.

1 Stimmen

+1 für das Standardzitat, was den Fehler betrifft: 2004 gemeldet, letzte Aktualisierung 2006 --> ich schätze, dass es niemanden wirklich interessiert, da es leicht zu umgehen ist :)

1voto

peoro Punkte 24751

using level1::foo; führt eine foo Funktion in level3 Klasse, die sich auf level1::foo .

In einer Verwendungsdeklaration, die als Member-Deklaration verwendet wird, muss die verschachtelte Namensangabe eine Basisklasse der zu denifizierenden Klasse nennen. Eine solche Verwendungsdeklaration leitet die Menge der Deklarationen ein, die durch die Suche nach dem Mitgliedsnamen gefunden werden.

Da jedoch level1::foo virtuell ist, nehme ich an, dass man beim Aufruf dieser Funktion auch level2::foo sollte icc also Recht haben.

Ich bin mir da jedenfalls nicht so sicher.

0voto

CashCow Punkte 29849

Der Weg, um Level1 zu bekommen, wäre natürlich Level1:

struct level3 : level2
{
   virtual void foo() { level1::foo(); }
};

Ihre "using"-Direktive scheint dem Compiler mitzuteilen, dass, wenn Sie eine Ebene3 haben und foo darauf aufrufen, er die Ebene1-Version aufrufen soll, aber er überschreibt diese nicht in der v-Tabelle.

gcc sieht wegen der Inkonsistenz falsch aus, bei icc bin ich mir nicht sicher, weil ich nicht weiß, was der Standard angibt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X