2017-05-17 6 views
3

Warum verwendet der Zuweisungsoperator bei einem dereferenzierten Zeiger auf eine rein abstrakte Schnittstelle keinen Compilerfehler? Wann könnte das jemals nützlich sein? Es scheint, dass es nur zu subtilen Fehlern führen kann, wie ich unten beschrieben habe.Warum verwendet der Zuweisungsoperator für einen dereferenzierten Zeiger kein Compilerfehler?

Um ein global zugängliches Objekt zu haben, das eine Schnittstelle mit einem Standardwert implementiert, die ich später überschreiben kann, muss ich ein Handle verwenden (Zeiger auf einen Zeiger - oder - Zeiger auf eine Std :: unique_ptr) oder gibt es einen anderen Ansatz?

#include <iostream> 

class Interface { 
public: 
    virtual int Value() = 0; 
}; 

class Implementation : public Interface { 
public: 
    Implementation(int value) : value(value) {} 
    int Value() override { 
    return value; 
    } 
    int value; 
}; 

// Set default value 
Interface* object = new Implementation(1); 
Implementation* object2 = new Implementation(2); 

int main() { 
    // Why is this line not a compiler error? 
    *object = Implementation(3); // Try to override default value 
    *object2 = Implementation(4); // Override default value 
    // This outputs "14", not "34", why? 
    std::cout << object->Value() << object2->Value(); 
    return 0; 
} 

Um diese Probleme zu erhalten, sowie die Möglichkeit, die Überschreiben des Standardwert in Unit-Tests einstellen, ich habe mit dem folgenden Ansatz gegangen.

// Set default value 
static std::unique_ptr<Interface> object(new Implementation(1)); 
void SetObject(std::unique_ptr<Interface> obj) { 
    object.reset(obj.release()); 
} 

int main() { 
    SetObject(std::make_unique<Implementation>(2)); // Override default value 
    std::cout << object->Value(); 
    return 0; 
} 

Antwort

5

C++ - Objekte erhalten standardmäßig eine operator= Methode, die vom Compiler generiert wird. Dieser Operator wendet einfach operator= auf jede Elementvariable an und es ist nicht virtuell. Das heißt, es wird mit den Mitgliedern des statischen Typs des deklarierten Zeigers arbeiten. Da Interface keine Mitglieder hat, werden keine Mitglieder kopiert. Implementation hat ein Mitglied, so dass das Mitglied kopiert wird.

+0

Ich sehe. Das eigentliche Problem war also meine Behauptung, dass "Interface" eine "reine abstrakte Schnittstelle" sei. Es ist tatsächlich nicht. Damit dies der Fall sein würde, müsste ich noch ein paar Dinge hinzufügen, wie das Löschen der Standardfunktionen, damit der Compiler-Fehler auftritt, den ich erwarten würde. "Schnittstelle & operator = (const Interface &) = löschen;" – AffluentOwl

+0

@AffluentOwl genau richtig. –

+0

Gibt es eine Möglichkeit, den Zuweisungsoperator auf der Schnittstelle virtuell zu machen und es so zu überschreiben, dass ich die endgültige Ausgabe meiner Hauptfunktion auf "34" setzen kann? – AffluentOwl

Verwandte Themen