2016-06-28 18 views
6

Ich mag aus einer Klasse mit den const Spezifizierer wie diese erben:vererben const Klasse

class Property 
{ 
    int get() const; 
    void set(int a); 
}; 

class ConstChild : public const Property 
{ 
    // Can never call A::set() with this class, even if 
    // the instantiation of this class is not const 
}; 

class NonConstChild : public Property 
{ 
    // Can call both A::set() and A::get() depending on 
    // the constness of instantiation of this class 
}; 

Mein Compiler gibt mir offensichtlich einen Fehler für das const Schlüsselwort in der zweiten Klassen Erklärung. Idealerweise möchte ich vermeiden, eine neue Klasse ReadOnlyProperty zu erstellen, von der ConstChild erben würde.

Kann ich irgendwie das Schlüsselwort const für die Vererbung verwenden?

  • Wenn nicht, haben Sie weitere Ideen, wie Sie dieses Problem lösen können?
+0

Sie 'ConstChild' mit einem Factory-Methode als die einzige Möglichkeit ausstatten könnte Konstruieren Sie Instanzen, indem Sie den Konstruktor 'privat' machen. Wenn es "const" Referenzen zurückgibt, wären Sie da. –

+3

Verwenden Sie Aggregation über Vererbung. –

+0

@ thomas-b-preusser Der Sinn davon ist, zu ermöglichen, dass 'ConstChild'' const'- und non-const'-Methoden selbst hat, dh Instantiierungen dieser Klasse haben müssen, die konstant und nicht konstant sind, während die ' Die Eigenschaft '' ''dieser Klasse wird immer konstant sein, dh die' set'-Methode kann nicht immer aufgerufen werden. –

Antwort

2

Ich möchte aus einer Klasse mit dem const Bezeichner“

viel wollen Sie irrelevant ist jedoch erben. Sie können es nicht. Das ist nicht gültig C++.

Kann ich irgendwie das Schlüsselwort const zur Vererbung verwenden? "

Nr

+1

Irgendwelche Gedanken zur zweiten Hälfte, "Wenn nicht, haben Sie andere Ideen, wie Sie dieses Problem lösen können?" –

0

Wenn Sie eine const Memberfunktion set erstellen, erhalten Sie, was Sie brauchen.

class Property 
{ 
    int get() const; 
    void set(int a); 
}; 

class ConstChild : public Property 
{ 
    void set(int a) const {} 
}; 

Der einzige Nachteil ist, dass ein schlauer Benutzer Ihre Absicht durch die Verwendung umgehen können:

ConstChild child; 
child.set(10); // Not OK by the compiler 

Property& base = child; 
base.set(10); // OK by the compiler 
+1

und was ist, wenn das 'void set (int a)' als 'virtual' deklariert wurde? – Mike

+0

Zusätzlich zu der Frage, wie trivial es ist, zu arbeiten, beantwortet dies nur die Frage, ob die OPs "Kann niemals' A :: set() 'heißen" bedeutet, kann es nennen, aber ohne etwas zu tun "... was ich irgendwie bezweifle. Man würde meinen, dass sie wirklich meinen, dass sie nicht aufgerufen werden kann, d. H. Sie würde einen Kompilierungsfehler erzeugen, wie jeder Versuch, eine Nicht-Const-Methode in der Art von echtem Const-Objekt zu nennen, zu dem sie eine Analogie gezogen haben. –

+1

Wenn die Instanz von "ConstChild" selbst "const" ist, könnte ich ihre 'set' Methode aufrufen, was es so aussehen lässt, als würde sie tatsächlich etwas tun, was nicht der Fall ist. Im Idealfall würde die Zeile 'Property & base = child;' einen Compilerfehler verursachen, da sie versucht, 'const'ness wegzuwerfen. –

4

Veränderlichkeit einführen später in Ihrem Vererbungsbaum und daraus entsprechend:

class Property 
{ 
    int get() const; 
}; 
class MutableProperty : public Property { 
{ 
    void set(int a); 
}; 

Und dann:

class ConstChild : public Property { ... }; 
class MutableChild : public MutableProperty { ... }; 
+1

Ich weiß, dass dies eine Lösung für das Problem selbst ist, obwohl ich angegeben habe, dass ich keine separate Klasse 'ReadOnlyProperty' erstellen möchte, was genau das ist, nur mit anderen Namen. –

+0

Grant - obwohl Ihre Benennung wirklich unerwünscht gewesen wäre, da eine 'Eigenschaft' auch eine' ReadOnlyProperty' wäre, obwohl sie nicht gelesen wird.Am Ende fürchte ich, dass Sie wirklich nach einer neuen Sprachfunktion fragen. Und es ist nicht unvernünftig, sich alle Modifikatoren vorzustellen, die regulären Mitgliedern erlaubt sind, auch mit Superklassen zu gehen. –

0

Verwenden Sie eine Datenelement- oder private Basisklasse anstelle der öffentlichen Basisklasse.

Dann steuern Sie den Zugriff auf dieses Mitglied.

Sie können die Property-Eigenschaft zu einer abstrakten Schnittstelle machen, wenn Sie polymorphes Verhalten benötigen.

0

Ich habe einen Trick, keine saubere Lösung.

class ConstChild : private Property 
{ 
    operator const Property() { return *this; } 
}; 

dann

ConstChild cc; 
cc.set(10); // ERROR 
cc().get(); 
+0

Dies ist auf vielen Ebenen falsch, zuerst wird der Konvertierungsoperator niemals aufgerufen, da gcc warns 'warning: Konvertierungsfunktion, die 'ConstChild' in seine Basisklasse 'Property' konvertiert, wird nie benutzt '. Dann stellt ConstChild nicht 'operator()' zur Verfügung, also ist 'cc()' ungültig. Vermutlich 'cc.operator const Property(). get() 'wäre, in diesem Fall würde 'operator const Property &' mehr Sinn ergeben. Und selbst dann ist die Syntax hässlich. Der einzige Gedanke, der einen Sinn ergeben könnte, ist, 'using Property :: get 'in' ConstChild' zu deklarieren. – alfC

0

Sie eine Template-Klasse und eine Spezialisierung für eine konstante Art verwenden können:

template<typename T> class base_property { 
    protected: 
     T value; 
    }; 
    template<typename T> class property : public base_property<T> { 
    public: 
     const T& get()const { return value; } 
     void set(const T& v){ value = v; } 
    }; 

    template<typename T> class property<const T> : public base_property<T> { 
    public: 
     const T& get()const { return value; } 
    }; 

    class ConstChild : public property<const int>{ }; 
+0

Dies ist im Grunde nur eine ganze separate Klasse zu erstellen. Nicht wirklich im Sinne dessen, was gefragt wurde! –

+0

, aber es beantwortet die zweite Frage: "Wenn nicht, haben Sie andere Ideen, wie Sie dieses Problem lösen können?", Und können eine Basisklasse für beide verwenden, die die Daten enthält –

+0

In diesem Fall warum mit der Vorlage zu tun? Habe einfach zwei verschiedene Klassen. Sie müssen sie trotzdem neu implementieren. –