Geschützte Daten in übergeordneter Klasse nicht in der Kinderklasse zur Verfügung?

StackOverflow https://stackoverflow.com/questions/1414506

  •  06-07-2019
  •  | 
  •  

Frage

Ich bin verwirrt. Ich dachte, geschützte Daten / beschreibbar durch die Kinder einer Klasse in C ++ gelesen wurde

Das folgende Snippet nicht in MS-Compiler

kompilieren
class A
{
protected:
  int data;
};

class B : public A
{
  public:

  B(A &a)
  {
    data = a.data;
  }
};

int main()
{
  A a;
  B b = a;
  return 0;
}

Fehlermeldung:

Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

demoFail.cpp
demoFail.cpp(12) : error C2248: 'A::data' : cannot access protected member declared in class 'A'
        demoFail.cpp(4) : see declaration of 'A::data'
        demoFail.cpp(2) : see declaration of 'A'

Was mache ich falsch?

War es hilfreich?

Lösung

Nach TC ++ PL, S. 404:

  

Eine abgeleitete Klasse kann eine Basisklasse zugreifen geschützte Mitglieder nur für Objekte der eigenen Art .... Dies verhindert, dass subtile Fehler, die sonst auftreten würden, wenn eine abgeleitete Klasse korrumpieren Daten zu anderen abgeleiteten Klassen gehören.

Natürlich, hier ist eine einfache Möglichkeit, dies für Ihren Fall zu beheben:

class A
{
protected:
    int data;
};

class B : public A
{
public:
    B(const A &a)
        : A(a)
    {
    }
};

int main()
{
    A a;
    B b = a;
    return 0;
}

Andere Tipps

Die C ++ Standard-sagt über geschützte nicht-statische Member bei 11.5/1

  

Als ein Freund oder eine Elementfunktion einer abgeleiteten Klasse eine geschützte nicht-statische Elementfunktion oder geschütztes nicht-statisches Datenelement einer Basisklasse verweist, gilt eine Zugriffsüberprüfung zusätzlich zu dem weiter oben in Klausel 11 beschrieben außer wenn ein Zeiger zu bilden, Glied (5.3.1), durch einen Zeiger auf der Bezugnahme auf oder Objekt der abgeleiteten Klasse selbst (von dieser Klasse abgeleitet, oder jede Klasse) sein (5.2.5) der Zugriff muß. Wenn der Zugriff einen Zeiger auf ein Element zu bilden ist, der nested-name-Spezifizierer wird die abgeleitete Klasse (oder eine Klasse von dieser Klasse abgeleitet) nennen.

Neben Dinge erwähnt früher von anderen Befestigungs (Konstruktor B ist privat), ich glaube, rlbond Weg es gut tun wird. Jedoch ist eine direkte Folge des vorstehenden Absatzes des Standard ist, dass die folgende möglich ist, einen Elementzeiger verwendet wird, die wohl ein Loch in dem Typsystem, natürlich

class B : public A {
public:
  B(A &a){
    int A::*dataptr = &B::data;
    data = a.*dataptr;
  }
};

Natürlich ist dieser Code nicht zu tun zu empfehlen, aber zeigt, dass Sie können darauf zugreifen, wenn Sie wirklich brauchen, um (ich habe so gesehen zum Ausdrucken verwendet wird, um eine std::stack, std::queue , std::priority_queue durch sein geschütztes Behälterelement c)

Zugriff

Sie nur nicht ein A Objekt in einem B Konstruktor kopieren. Die Absicht ist, die Initialisierung von A Mitgliedern zu seinem eigenen Konstruktor zu verlassen:

struct A { 
  A( const A& a ): data( a.data ) {}
  protected: int data; 
};

struct B : public A {
  B( const A& a ): A( a ) {}
};

Der Konstruktor von B ist privat. Wenn Sie nichts angeben, in einer Klasse, ist der Standard-Modifikator privaten (für structs es ist öffentlich). So in diesem Beispiel das Problem ist, dass Sie nicht B. konstruieren können, wenn Sie öffentlich hinzufügen B Konstruktor anoter Problem:

B hat das Recht, den Teil A so zu ändern, es ergibt sich aber kein anderes A wie in diesem Fall.

Sie können auf folgende Arten tun:

class A
{
public:
  A()
      : data(0)
  {
  }
  A(A &a)
  {
    data = a.data;
  }
protected:
  int data;
};

class B : public A
{
public:
  B(A &a)
      : A(a)
  {
  }
};

int main()
{
  A a;
  B b = a;
  return 0;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top