Question

Une question à propos de constructeur protégé. J'ai appris que le constructeur protégé peut être utilisé dans la classe dérivée. Comment jamais, je l'ai trouvé le code ci-dessous présente une erreur. Pourquoi se fait-il comme ça?

class A
{
    protected:
        A(){}
};

class B: public A {
    public:
        B() {
            A* f=new A();           // Why it is not working here
        }
};
Était-ce utile?

La solution

Cela n'a rien à voir avec les constructeurs spécifiquement. Ceci est juste comment fonctionne l'accès protected.

Le prescripteur d'accès protected façon fonctionne, il permet à la B de classe dérivée pour accéder au contenu d'un objet de classe de base A uniquement lorsque cet objet de A de classe est une sous-objet de classe B . Cela signifie que la seule chose que vous pouvez faire dans votre code est d'accéder au contenu de A à B: vous pouvez accéder aux membres de A par un pointeur de type B * (ou une référence de type B &) . Mais vous ne peut pas accéder aux mêmes membres par un pointeur de type A * (ou A & de référence).

Prenons l'exemple suivant

class A {
protected:
  int i;
};

class B : A  {
  void foo() {
    i = 0;        // OK
    this->i = 0;  // OK

    B *pb = this;
    pb->i = 0;    // OK

    A *pa = this;
    pa->i = 0;    // ERROR

    ((A *) this)->i = 0; // ERROR
  }
};

Dans le B::foo ci-dessus, vous pouvez accéder à l'élément de base A::i en utilisant tout simplement la syntaxe i. Cela équivaut à l'utilisation de la syntaxe this->i. Les deux vont travailler, parce que le pointeur this est de type B *, à savoir que vous accédez à A::i complet un pointeur de type B *. Ceci est exactement ce que le spécificateur d'accès protected est censé permettre. L'accès par pointeur pb travaille pour la même raison.

Toutefois, lorsque vous « convertir » pointeur this taper A *, vous ne pouvez plus A::i d'accès par ce nouveau pointeur, même si vous essayez encore ils accéder à même membre que précédemment.

Appliqué aux constructeurs, le spécificateur d'accès protected a un effet très spécifique: un constructeur protégé ne peut être utilisé pour initialiser la classe de base des sous-objets. Il ne peut pas être utilisé pour initialiser des objets autonomes (qui est ce que vous essayez de faire). En d'autres termes, les constructeurs protégés sont une autre façon de mettre en œuvre le concept de classe abstraite en C ++ (ainsi que des méthodes virtuelles pures). Si les constructeurs de votre classe sont protégés, votre classe est effectivement abstrait . Vous ne pouvez pas l'utiliser pour définir des objets indépendants « de l'extérieur ». (Bien sûr, ce qui précède ne s'applique pas dans amis, ainsi que dans la classe elle-même).

Autres conseils

Quand une classe de base a un constructeur protégé, vous ne pouvez pas instancier la classe directement. Mais vous pouvez le faire appeler le constructeur du constructeur de la classe de base:

class A {

protected:
   A() {}
};

class B: public A {
public:
   B() : A() // allowed to access constructor like this
   {
      A* f = new A(); // Not allowed to access constructor like this!
   }
};

Un appel direct au constructeur comme indiqué ci-dessous vous donne l'erreur suivante avec la version gcc 4.1.2:

      A* f = new A(); // Not allowed to access constructor like this!

test.cpp:4: error: A::A() is protected

Cependant, vous cet appel au constructeur donne aucune erreur:

   B() : A() // allowed to access constructor like this

La raison de ceci est que le second appel accède au constructeur A () par héritage, ce qui est permis. Cependant, cela essaie de créer explicitement une nouvelle instance de A () en appelant le constructeur directement:

      A* f = new A(); // Not allowed to access constructor like this!

Cela peut sembler peu intuitif, comme B devrait être en mesure d'accéder au constructeur de A parce que B hérite de A. Toutefois, si vous déclarez un constructeur protégé en C ++, vous ne pouvez pas créer une instance de cette classe, sauf par héritage ou une relation d'ami.

Permettez-moi de ma réponse dans les étapes:

1) Constructors ne sont pas Héritée et pourquoi dans la classe dérivée, ils ne peuvent pas être plus monté.
2) Les constructeurs sont invoquées et non appelé.
3) Si vous avez déclaré une fonction simple mot à dire protégé void print () puis essayé d'appeler en B, il aurait travaillé. Cela se produit bcoz, B a hérité de cette fonction.

4) Quand vous faites quelque chose comme ceci b: un (), vous invoquez le constructeur et qui est autorisé
. 5) Essayez de faire une classe B ami de A, puis courir et voir si cela fonctionne.

Hope this helps.

J'ai eu la même question que cela, et ce lien me faire clair.

cppreference dit comme ceci:

Protected members form the interface for the derived classes (which is   

distinct from the public interface of the class). 

A protected member of a class Base can only be accessed 

1) by the members and friends of Base 

2) by the members and friends (until C++17) of any class derived from Base, but only when operating on an object of a type that is derived from Base (including this)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top