wake-up-neo.com

Geschützte Member der Eltern mit Initialisierungsliste initialisieren (C++)

Ist es möglich, die Initialisierungsliste des Konstruktors einer untergeordneten Klasse zum Initialisieren von Datenmitgliedern zu verwenden, die in der übergeordneten Klasse als geschützt deklariert sind? Ich kann es nicht zum Laufen bringen. Ich kann damit umgehen, aber es wäre schön, wenn ich nicht muss.

Einige Beispielcodes:

class Parent
{
protected:
    std::string something;
};

class Child : public Parent
{
private:
    Child() : something("Hello, World!")
    {
    }
};

Wenn ich das versuche, sagt mir der Compiler: "Klasse 'Child' hat kein Feld mit dem Namen 'Etwas'". Ist so etwas möglich? Wenn ja, wie lautet die Syntax?

Danke vielmals!

117
Stephen

Es ist nicht in der von Ihnen beschriebenen Weise möglich. Sie müssen der Basisklasse einen Konstruktor hinzufügen (könnte geschützt werden), um ihn weiterzuleiten. So etwas wie:

class Parent
{
protected:
    Parent( const std::string& something ) : something( something )
    {}

    std::string something;
}

class Child : public Parent
{
private:
    Child() : Parent("Hello, World!")
    {
    }
}
110
philsquared

Wenn der Compiler die Initialisierungsliste findet, muss das abgeleitete Klassenobjekt noch gebildet werden. Der Basisklassenkonstruktor wurde bis dahin nicht aufgerufen. Erst nachdem der Konstruktor der Basisklasse aufgerufen wurde, tritt something auf. Daher das Problem. Wenn Sie den Basisklassenkonstruktor nicht explizit aufrufen, erledigt der Compiler dies für Sie (indem er den entsprechenden trivialen Konstruktor für die Basisklasse generiert). Dadurch wird der Member something standardmäßig initialisiert. 

Von C++ 0x Entwurf:

12.6.2 Basis und Member initialisieren

2 Namen in einer Speicherinitialisierer-ID lauten im Rahmen des .__ nachgeschlagen. Klasse des Konstruktors und falls nicht gefunden. in diesem Umfang werden in der .__ nachgeschlagen. Bereich, der die .__ des Konstruktors enthält. Definition. [Hinweis: wenn der Die Klasse des Konstruktors enthält ein Mitglied mit dem gleichen Namen wie eine direkte oder virtuelle Basisklasse der Klasse a mem-initializer-id benennt das Mitglied oder Basisklasse und besteht aus einem einzigen Bezeichner bezieht sich auf den Klassenmitglied . Eine meminitializer-id für das ausgeblendete Die Basisklasse kann mit einem .__ angegeben werden. qualifizierter Name. —Ender Hinweis] Wenn nicht der mem-initializer-id benennt die Konstruktorklasse, nicht statische Daten Mitglied der Klasse des Konstruktors oder ein direkte oder virtuelle Basis dieser Klasse Der mem-Initialisierer ist schlecht geformt.

Anmerkung: Schwerpunkt meiner.

59
dirkgently

Sie können nicht Mitglieder der übergeordneten Klasse in der Initialisierungsliste des Konstruktors für abgeleitete Klassen initialisieren. Es ist egal, ob sie geschützt sind, öffentlich sind oder etwas anderes.

In Ihrem Beispiel ist Mitglied something Mitglied der Klasse Parent. Dies bedeutet, dass es nur in der Konstruktor-Initialisierungsliste der Klasse Parent initialisiert werden kann.

12
AnT

Vielleicht können Sie es auf diese Weise mit dem Schlüsselwort "using" versuchen.

class Parent
{

protected:
std::string something;
};

class Child : public Parent
{

private:
using Parent::something;
Child()
{
    something="Hello, World!";
}
};
0
Aitor