2009-09-24 29 views
9

¿Es posible deshacerse de error C2243?Deshacerse del error C2243

class B {}; 
class D : protected B {}; 

D d; 
B *p = &d; // conversion from 'D *' to 'B &' exists, but is inaccessible 

tuve este error en mi aplicación y al final he logrado compilar al hacer una conversión explícita:

D d; 
B *p = (B*)&d; 

no puedo entender por qué al hacer la clase D heredado protegida desde B hace que la conversión implícita sea inaccesible.

Me trataron de evitar la conversión explícita mediante la creación de un operador B() en la clase D con el fin de hacer la conversión accesible:

class B {}; 
class D : protected B 
{ 
public: 
operator B() {return *this;} 
}; 

pero no hay manera.

¿Alguna otra solución para evitar la conversión explícita?

Respuesta

17

Si desea permitir la conversión, debe utilizar herencia pública.

Al usar una herencia protegida o privada, declara que el hecho de que el tipo derivado herede de la clase base es un detalle que no debería ser visible desde el exterior: es por eso que está obteniendo ese error.

Debe considerar la herencia no pública solo como como una forma de composición con la posibilidad adicional de anular los métodos.

+0

¿Qué hay de dar acceso sólo a la const interfaz de la clase base? Entonces, ¿heredas privadamente y permites lanzar a const base &? Preguntar porque no puede hacer que funcione en MSVC ... –

+0

Solo respondiendo a mí mismo, necesita manejar la clase por agregación, no herencia, de lo contrario, MSVC se confunde e intenta resolver la conversión por herencia privada (ocultando el operador de conversión) –

8

Porque protected y private herencia no son is-a relación, son simplemente sintaxis azúcar para la composición. Sus clases se pueden reescribir exactamente así, pero se pierde la conveniencia de dejar que el compilador definen b para usted, y el uso de los miembros b directamente en lugar de referirse a ella de forma explícita:

class D 
{ 
    protected: 
    B b; 
}; 

Para el segundo punto de su pregunta:

operator B() {return *this;} 

Esta línea tiene que ver con B y D. D * y B * son totalmente diferentes de B y D, ¡aunque son consejos para ellos! para lanzar punteros, podría reinterpretar el puntero:

B *p = reinterpret_cast<B*>(&d); // TOTALLY WRONG, although it compiles :) 

¡No haga la línea de arriba! Creo que podrías darnos más información de lo que estás tratando de lograr.

2

Debido a que de los niños D y D, nadie sabe que son padres e hijos, por lo que debe hacerlo explícitamente.

Eso es lo que significa herencia protegida, solo su familia (hijos) sabrá que usted hereda. Y podría usarlo, por ejemplo, en un método secundario, allí una conversión implícita sería legal.

Si desea tener una conversión implícita de sus hijos, debe hacerlo público para que todos lo sepan.

0

¿Intentaste hacer que el operador B() public en la clase D? En el código que mostró, estaría marcado como protegido y aún inaccesible. Pero evitaría los operadores de conversión en general si es posible.

Aún así, heredar la protección B significa que tiene la intención de evitar hacer B * p = & d. Imagine que B fuera realmente una variable de miembro protegida en la parte superior de D. Al igual que no puede acceder a D.b en ese caso, no puede acceder a d como B *, a menos que lo descarte.

O herede B públicamente, o use sus moldes. Me gustaría heredar B públicamente, porque heredarlo protegido básicamente dice "No me uses como B", lo que intentas hacer de todos modos.

+1

haciendo que el operador B() público tampoco funciona –

2

El problema aquí es que está tratando de hacer una corrida final alrededor de la información que oculta que proporciona el atributo protected. Si desea acceder a una instancia de D como B, ¿por qué la heredó como protegida en lugar de pública ?. Lo que está diciendo al usar herencia protegida es que desea que solo las instancias de D y sus descendientes conozcan el componente B. Necesita mirar nuevamente lo que quiere lograr.

El antiguo elenco de estilo C que está utilizando no tiene la sutileza de los moldes de C++ más nuevos, por lo que le da código que compilará pero el problema está realmente en la herencia.

0

Porque nadie sabe que están fuera de padre-hijo, sólo se puede realizar esta acción en class.This derivados D's es un ejemplo (de prueba en Visual Studio 2013):

class BASE{}; 

class BASE1 :protected BASE{}; 

class BASE2 :protected BASE1 
{ 
public: 
    void func(BASE &a, BASE1 &b){a = b;} 
}; 

void main() 
{ 
    BASE a; 
    BASE1 b; 
    BASE2 c; 

    c.func(a, b);; 
    system("pause"); 
} 
Cuestiones relacionadas