2016-05-18 18 views
1

Angenommen, wir haben ein folgendes Stück Code:Bitte klären const Qualifier Ausbreitung

class Base { 
    public: 
    int a = 5; 
}; 

class Derived : public Base { 
    public: 
    Base *parent_ = new Base; 
    Base* parent() const { return parent_; } 
}; 

void f(const Derived *derived) { 
    Base *p = derived->parent(); 
    p->a = 10; // <- is this correct? 
} 

Ich persönlich denke, hier ist ein Problem:

In Funktion f nehmen wir einen Zeiger auf const Objekt der Klasse Derived. Dies macht jedes Mitglied davon auch const also parent_ wird const Base *. Wenn es const ist, sollten wir nicht in der Lage sein, das Objekt zu modifizieren, auf das der Zeiger zeigt.

Wo liege ich falsch?

+0

'int a = 5;' - ist das C++ 11? – sashoalm

+2

'parent_' ist vom Typ' Base * const', nicht 'const Base *'. – Quentin

+0

@ashoalm ja, ist es.Aber ich habe die Frage nicht mit 'C++ 11' versehen, weil das irrelevant ist. –

Antwort

7

Dies macht jedes Mitglied davon auch const so parent_ wird const Base *.

Nein, der Zeiger wird const selbst, nicht das Objekt, auf das er zeigt. So parent_ wird Base * const, nicht const Base *, und Ihr Code ist gültig.

4
Base* parent() const { return parent_; } 

Leider ist dies ein Problem mit C++. Methode ist const, aber es ist eine nicht-const Zeiger zurückkehrt, die folgende Operation ermöglichen würde, um erfolgreich zu sein:

p->a = 10; // <- is this correct? 

Es ist Aufgabe des Programmierers nicht nicht-const Zeiger oder Referenzen von Funktionen zurückzukehren (Methode ist const oder nicht).

+0

Laut der Antwort von @songyuanyao ist dies kein Problem, da wir das Objekt ändern, das "nicht-konstant" bleibt, weil das einzige, was durch "const propagation" "const" wird, der Zeiger selbst ist. –

+0

@VictorPolevoy Ich würde sagen, es ist ein Problem. Du sprichst nicht die Sprache, aber du brichst logische Konsequenz. – TartanLlama

0

Wie tobi303 zeigt unten, ist diese Antwort falsch. Halte es hier wegen der folgenden Diskussion.


könnte ich falsch sein, aber diese Zeile:

Base* parent() const { return parent_; } 

nicht erwähnt nichts über const Objekte zurück. Es entspricht

Base* parent() const { return this->parent_; } 

wo this ist const Derived*, aber parent_ ist noch Base*.

+3

das Mitglied eines 'const'-Objekts ist auch' const ', sonst wäre die ganze' const'-Geschichte für öffentliche Mitglieder nutzlos – user463035818

+1

@ tobi303 Sie scheinen den Unterschied zwischen 'const T *' und 'T * const' nicht zu verstehen –

+2

'this' ist' const Abgeleitet * const', 'parent_' ist' Base * const'. – songyuanyao

0

Eine const-Methode verhindert nur, dass die Methode nicht veränderbare Datenelemente der Klasse ändert.

Wenn Sie wollen nicht die Änderung von a erlauben und nicht wollen, um die Klasse zu aktualisieren, müssen Sie schreiben:

const Base *p = derived->parent(); 

Allerdings würde ich empfehlen Sie nicht nicht konstante Datenelemente zurück aus einer Klasse als ref oder Zeiger, da dies das Datenkapselungskonzept von C++ durchbricht. Dies gilt natürlich auch für die Öffentlichkeit a.