2012-11-19 13 views
7

Vielleicht ich habe zwei Schnittstellen mit dem gleichen Funktionsnamen und Parameter, jedoch mit unterschiedlichen Rückgabewerte:C++ Wie multipliziert man Vererbungen von Interfaces mit unterschiedlichen Rückgabetypen?

struct A { virtual void foo() = 0; }; 
struct B { virtual int foo() = 0; }; 

Wie Klasse C zu definieren, das erbt diese Schnittstellen (wenn es natürlich möglich ist)? Zum Beispiel schreibe ich einige Pseudo-Code, der nicht kompiliert hat:

// this code is fake, it doesn't compiled!! 
struct C : A, B 
{ 
    // how to tell compiler what method using if referenced from C? 
    using void foo(); // incorrect in VS 2012 
    // and override A::foo() and B::foo()? 
    virtual void foo() { std::cout << "void C::foo();\n"; } // incorrect 
    virtual int foo() { std::cout << "int C::foo();\n"; return 0; } // incorrect 
} 
// ... for use in code 
C c; 
A &a = c; 
B &b = c; 
c.foo();  // call void C::foo() when reference from C instance 
a.foo();  // call void C::foo() when reference from A instance 
b.foo();  // call int C::foo() when reference from B instance 
+1

Warum sollten Sie so etwas wollen? –

+2

vielleicht besitzt er nicht A und B; muss aber C machen, das beides implementiert. Scheint eine vernünftige Frage – pm100

+1

Das ist in C++ nicht möglich (nicht wie du es codiert hast). Funktionen werden anhand ihrer Parametertypen und nicht anhand ihrer Rückgabetypen identifiziert. –

Antwort

4

es nicht möglich ist, aber nicht wegen der Mehrfachvererbung. Mehrdeutigkeit tritt aufgrund ungültiger Überlast von foo in Klasse C auf. Sie können nicht int foo() und void foo() haben, da der Rückgabetyp nicht Teil der Funktionssignatur ist. Daher kann der Compiler die Aufrufe von foo nicht auflösen. Sie können Ihre Schnittstelle als eine Vereinigung der Klassen A und B betrachten, so dass das Problem logischerweise bereits vor der eigentlichen Vererbung vorliegt. Da aus der Compilerperspektive A und B zwei unterschiedliche und nicht verwandte Typen sind, gibt es kein Problem beim Kompilieren, und der Fehler wird bis zum Punkt der tatsächlichen Vereinigung in Klasse C verzögert.

mehr Siehe hier über Funktionssignaturen und Überlastung: Is the return type part of the function signature?

1

Es ist nicht möglich, eine virtuelle Funktion des Rückgabetyp mit der gleichen Signatur zu überschreiben (wie @ icepack Antwort erklärt). Ein alternativer Ansatz könnte eine Vorlagenbasisklasse haben, die foo() mit einem als Vorlagenparameter angegebenen Rückgabetyp deklariert und Spezialisierungen für konkrete Rückgabeparametertypen bereitstellt.

Dies wäre eine Verallgemeinerung des Vorschlags von @Dietmar Kühl.

1

Was Sie können tun ist, alle das gemeinsame Material in eine virtual Basis zu stellen, sagen C_base und überschreiben die widersprüchlichen virtual Funktionen in Hilfsklassen, die jeweils. Da das gemeinsame Zeug für C ist leicht zugänglich in ist im Wesentlichen wie in einem am meisten abgeleiteten C. Schließlich Sie C Klasse, nur weil die Klasse Dinge Strang ziehen:

struct A { virtual void foo() = 0; }; 
struct B { virtual int foo() = 0; }; 

struct C_base { int all_data; }; 

struct A_aux: virtual C_base, A { 
    void foo() { std::cout << "A_aux::foo()\n"; } 
}; 

struct B_aux: virtual C_base, B { 
    int foo() { std::cout << "B_aux::foo()\n"; return 0; } 
}; 

struct C : A_aux, B_aux 
{ 
    using A_aux::foo; 
}; 
2

Sie explizit qualifizieren können.

class C : A, B { 
public: 
    void A::foo() { ... } 
    int B::foo() { ... } 
}; 

Edit:

Dies scheint ein MSVC Erweiterung, anstatt Standards.

+0

Ich dachte auch, aber der Versuch, es zu kompilieren, scheiterte für mich. Ich habe die richtige Syntax noch nicht gefunden ... –

+0

Ich habe den Grund gefunden. Ich denke, es ist eine MSVC-Erweiterung.Es erscheint merkwürdig, dass der Standard diesen Fall nicht abdecken würde (und doppelt seltsam, dass eine MSVC-Erweiterung tatsächlich ein Loch flickt, anstatt mehrere zu verursachen: P). – Puppy

+0

Gute Sachen. Gibt es einen anderen Weg als das Casting, um sie über die Klasse 'C' aufzurufen? – SomeWittyUsername

Verwandte Themen