¿Por qué el constructor protegido genera un error este código?

Una pregunta sobre el constructor protegido. Aprendí que el constructor protegido se puede usar en la clase derivada. Sin embargo, encontré que el código a continuación tiene un error. ¿Por qué sucede así?

class A { protected: A(){} }; class B: public A { public: B() { A* f=new A(); // Why it is not working here } }; 

    Esto no tiene nada que ver con los constructores específicamente. Así es como funciona el acceso protected .

    La forma en que funciona el especificador de acceso protected , permite que la clase derivada B acceda al contenido de un objeto de clase base A solo cuando ese objeto de clase A es un subobjeto de clase B Eso significa que lo único que puede hacer en su código es acceder a los contenidos de A a B : puede acceder a los miembros de A través de un puntero de tipo B * (o una referencia de tipo B & ). Pero no puede acceder a los mismos miembros a través de un puntero de tipo A * (o referencia A & ).

    Considera el siguiente ejemplo

     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 } }; 

    En el anterior B::foo , puede acceder al miembro base A::i utilizando simplemente la syntax i . Esto es equivalente a usar this->i syntax. Ambos funcionarán, porque el puntero tiene el tipo B * , es decir, está accediendo a A::i través de un puntero de tipo B * . Esto es exactamente lo que se supone que permite el especificador de acceso protected . El acceso a través del puntero pb funciona por la misma razón.

    Sin embargo, cuando “convierte” this puntero a tipo A * , ya no podrá acceder a A::i través de ese nuevo puntero, aunque todavía intente acceder al mismo miembro que antes.

    Cuando se aplica a constructores, el especificador de acceso protected tiene un efecto muy específico: un constructor protegido solo puede usarse para inicializar subobjetos de clase base. No se puede usar para inicializar objetos independientes (que es lo que estabas tratando de hacer). En otras palabras, los constructores protegidos son otra forma de implementar el concepto de clase abstracta en C ++ (junto con métodos virtuales puros). Si los constructores de su clase están protegidos, entonces su clase es efectivamente abstracta . No puede usarlo para definir objetos independientes “desde afuera”. (Por supuesto, lo anterior no se aplica dentro de amigos, ni tampoco dentro de la clase).

    Cuando una clase base tiene un constructor protegido, no puede instanciar la clase directamente. Pero puede hacer esto para llamar al constructor desde el constructor de la clase 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! } }; 

    Una llamada directa al constructor como se muestra a continuación le da el siguiente error con gcc versión 4.1.2:

      A* f = new A(); // Not allowed to access constructor like this! test.cpp:4: error: A::A() is protected 

    Sin embargo, esta llamada al constructor no da ningún error:

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

    La razón detrás de esto es que la segunda llamada accede al constructor A () a través de la herencia, lo que está permitido. Sin embargo, esto intenta crear explícitamente una nueva instancia de A () llamando al constructor directamente:

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

    Esto puede parecer poco intuitivo, ya que B debería poder acceder al constructor de A porque B hereda de A. Sin embargo, si declaras un constructor protegido en C ++, no puedes crear una instancia de esa clase excepto por herencia o una relación de amigo.

    Déjame poner mi respuesta en pasos:

    1) Los constructores no se heredan y, por lo tanto, en la clase derivada, no pueden sobreestimarse.
    2) Los constructores son invocados y no llamados.
    3) Si ha declarado una función simple en A, digamos protected void print () y luego intentó llamarla en B, hubiera funcionado. Esto sucede bcoz, B ha heredado esta función.

    4) Cuando haces algo como esto b: a (), estás invocando al constructor y eso está permitido.
    5) Intenta hacer B una clase de amigo de A y luego ejecuta y verifica si funciona.

    Espero que esto ayude.

    Tenía la misma pregunta que esta, y este enlace me deja en claro.

    cppreference dice así:

     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)