2015-06-05 12 views

Antwort

7

[class.virtual]/p7, Hervorhebung von mir:

Der Rückgabetyp einer übergeordneten Funktion ist entweder identisch mit der Rückgabetyp sein der überlagerten Funktion oder kovariante mit den Klassen der Funktionen. Wenn eine Funktion D::f eine Funktion B::f überschreibt, sind die Rückgabetypen der Funktionen covariant, wenn sie folgende Kriterien erfüllen :

  • beide sind Zeiger auf Klassen, sind beide lvalue Verweise auf Klassen oder beide sind rvalue Verweise auf Klassen [Fußnote weggelassen]
  • [...]

Von Seiten 294-5 von D&E:

Afer einige Betrachtung der Alternativen entschieden wir uns überwiegendes eines B* von einem D* und eines B& von einem D& wo B ein zu erlauben, zugängliche Basis von D. Zusätzlich kann const hinzugefügt oder abgezogen werden, wo immer das sicher ist. Wir beschließen, nicht die Regeln zu entspannen technisch machbar Konvertierungen ermöglichen wie ein D zu einer zugänglichen Basis B, ein D zu einem X für die D eine Umwandlung hat, int* zu void*, double zu int etc. Wir haben das Gefühl, dass Die Vorteile von , die solche Umwandlungen durch Überschreiben zulassen, würden die Implementierungskosten und das Potenzial für verwirrende Benutzer nicht aufwiegen.

+2

Wäre nett, wenn Sie das "warum" hinter diesem Entwurf erklären könnten. – Mehrdad

+1

@Mehrdad Ein D & E-Zitat hinzugefügt. –

+0

Wenn ich mir das Problem mit der Kovarianz und den Einschränkungen von Namespaces in C++ anschaue, kann ich die Gründe für das Objekt und die Pakete von Java erkennen. – ady

0

Das Covariant-Rückgabetyp-Feature ist, wenn eine abgeleitete Klasse einen spezifischeren/schmaleren Rückgabetyp für eine überschriebene Funktion bereitstellt. Der Rückgabewert der abgeleiteten Klasse wird als kovariant bezeichnet.

int * ist nicht vom Typ void *, während so etwas wie dies nicht zeigt covariant Rückgabetyp:

struct Base { 
    virtual void *foo(); 
    virtual Base* func(); 
}; 
struct Derived : Base { 
// int *foo(); 
    Derived* func(); //COVARIANT RETURN TYPE 
}; 
+0

Sie erklären die Definition von "Covariance", das OP fragt "Warum". – iammilind

1

Die Kovarianz zwischen void* und T* ist nicht erlaubt, weil:

1. Mangel an Kohärenz.

Der aktuelle Weg der Kovarianz ist trivial zu verstehen und schafft keine Verwirrung.
Stellen Sie sich vor void* Art der Kovarianz ist erlaubt. Für eine Stufe der Ableitung ist in Ordnung, aber dann wird es Verwirrung schaffen. z.B .:

struct void_ { virtual void* foo(); }; 
struct int_ : void_ { virtual int* foo(); }; 
struct double_ : int_ { virtual double* foo(); }; // int* to double* or void* to double* 

In der dritten Hierarchie der struct double_, wird der Benutzer verwirrt, dass, obwohl double* zu int* nicht möglich ist, warum wird der Code noch kompilieren? Nur nach Überprüfung der obersten Klasse void_ ist bekannt, dass es wegen double*void* "kovariant" ist. Das Gleiche gilt für Compiler als auch :-)

2. Ausgabe mit den Referenzen

Bei Klassen, Rückkehr B&/D*/DD* möglich ist. Aber gleiche Sache ist nicht möglich, mit void& und damit int& usw.

3. Mischen von Kovarianzen

Wenn void* darf dann auch unbeabsichtigt erlaubt folgt.

struct void_ { virtual void* foo(); }; 
struct Base : void_ { virtual Base* foo(); }; 
struct Derived : Base { virtual int* foo(); }; // Look at `int*` 

Was zu Verwirrung führt.