2010-09-09 14 views
19

Aquí está mi código -¿Por qué la conversión entre derivada * a base * falla con herencia privada?

#include<iostream> 
using namespace std; 

class base 
{ 
public: 
    void sid() 
    { 
    } 
}; 

class derived : private base 
{ 
public: 
    void sid() 
    { 
    } 
}; 

int main() 
{ 
    base * ptr; 
    ptr = new derived; // error: 'base' is an inaccessible base of 'derived' 
    ptr->sid(); 
    return 0; 
} 

Esto da un error de tiempo de compilación.

error: 'base' is an inaccessible base of 'derived' 

Desde el compilador tratará de llamar a la clase base sid() ¿por qué recibo este error? Puede alguien por favor explicar esto.

+0

No declaró el método 'virtual'. ¿Qué error es el que está recibiendo exactamente? – Dirk

+8

En su forma actual, esto no tiene nada que ver con la función 'sid()'. Está utilizando una herencia privada, por lo tanto, la conversión de 'derived *' a 'base *' está fallando. ¿Es eso lo que estás preguntando o es algo relacionado con el método 'sid()'? – Naveen

+1

posible duplicado de [clase derivada protegida] (http://stackoverflow.com/questions/433965/protected-derived-class) – kennytm

Respuesta

16

$ 11,2/4 Unidos-

A base class B of N is accessible at R, if

  • an invented public member of B would be a public member of N, or
  • R occurs in a member or friend of class N, and an invented public member of B would be a private or protected member of N, or
  • R occurs in a member or friend of a class P derived from N, and an invented public member of B would be a private or protected member of P, or
  • there exists a class S such that B is a base class of S accessible at R and S is a base class of N accessible at R."

Aquí 'B' es 'base', 'N' es 'Derivado' y 'R' es principal.

  1. Considere la 2ª viñeta- 'R ocurre en un miembro o amigo de una clase N, ...'. Esta cláusula no se aplica ya que 'R' (principal) no es miembro ni amigo de 'N' (derivada)

  2. Considere la tercera viñeta- 'R ocurre en un miembro o amigo de una clase P ... . '. Esta Noel tampoco se aplica por las mismas razones que el anterior

  3. Considere el cuarto de bala Una vez más, esta cláusula no se aplica

Por lo tanto podemos concluir que la 'base' no es una clase de acceso 'Derivado'.

$ 11,2/5 estados -

If a base class is accessible, one can implicitly convert a pointer to a derived class to a pointer to that base class (4.10, 4.11). [ Note: it follows that members and friends of a class X can implicitly convert an X* to a pointer to a private or protected immediate base class of X. —end note ]

Desde Base no es una clase accesible de Derived cuando se accede en main, la conversión estándar de la clase derivada de la clase base está mal formada. De ahí el error.

EDIT 2:

Estudiar los mensajes de error de algunos compiladores populares y que debería ayudar a obtener una mejor comprensión.Observe cómo la palabra "inaccesible" aparece con tanta frecuencia y coherencia en todos los mensajes de error

Las referencias provienen del borrador del estándar N3000. Estoy todavía a descargar el último borrador :)

GCC prog.cpp: In function ‘int main()’: prog.cpp:27: error: ‘base’ is an inaccessible base of ‘derived’

Comeau Online "ComeauTest.c", line 26: error: conversion to inaccessible base class "base" is not allowed ptr = new derived;

VS2010 error C2243: 'type cast' : conversion from 'derived *' to 'base *' exists, but is inaccessible

+0

Puede proporcionarnos su referencia. – Bruce

+0

@Bruce: Oh, lo siento, olvidé mencionar que las referencias son del borrador del estándar N3000. Encontré que C++ 03 tiene algunas declaraciones confusas para entender este concepto. Actualizaré mi publicación según corresponda – Chubsdad

+0

Consulte las respuestas de Douglas Leeder y ereOn para obtener soluciones rápidas y legibles para el ser humano. – mwjohnson

35

Sospecho que el problema es que no se puede convertir un puntero derivado a un puntero base, ya que la herencia es privada.

+0

¿Por qué no puedo hacer esto? ¿Cuáles son los problemas de implementación en esto? – Bruce

+2

La herencia privada significa que no desea que se pueda acceder a la interfaz de la clase base con otro código que el código de clase hijo. – Klaim

+7

Realmente no tenía ganas de pasar el tiempo interpretando la respuesta de Chubsdad y esto era exactamente lo que necesitaba saber. Faltaba una declaración 'pública' en mi definición de clase derivada – User

0

Debe declarar su función sid() en la clase base como virtual. Una función virtual puede ser reemplazada por una clase derivada. De lo contrario, es probable que obtenga un error de compilación.

+4

Ya sabes, ME ODIO cuando las personas rechazan y no dejan ningún comentario. –

+0

No voté negativamente esta respuesta, pero creo que está equivocada. He visto compiladores dar * advertencias * para ocultar una función de clase base con una clase derivada, pero nunca un error. –

5

Prueba esto:

#include<iostream> 
#include<conio.h> 
using namespace std; 

class base 
{ 
     private: 
     public: 
      virtual void sid() // You might want to declare sid virtual 
      { 
        cout<<"base"; 
      } 
      virtual ~base() // You then probably need a virtual destructor as well. 
      { 
      } 
}; 

class derived : public base //public inheritance 
{ 
     private: 
     public: 
      void sid() 
      { 
        cout<<"derived"; 
      } 
}; 

int main() 
{ 
    base * ptr; 
    ptr = new derived; 
    ptr->sid(); 
    getch(); 
    return 0; 
} 
+0

¿Quiso decir 'virtual void sid()'? También necesita que el destructor de la clase base sea 'virtual'. – Naveen

+0

@Naveen: Gracias. Estaba en camino de agregar el destructor;) También sí, el 'privado' era un error tipográfico. – ereOn

+0

El destructor virtual es una buena idea. Poner virtual en la función sid es contrario a un objetivo declarado del cartel original. –

6

Usted sabe que class derived hereda de class base, pero la función main() no lo sabe. La razón por la cual la función main() no lo sabe es que usted hizo que class derived herede PRIVADA del class base.

Por lo tanto, cuando intenta asignar new derived a ptr, los tipos de puntero no son compatibles.

+0

@WP: ¿Puede explicar su respuesta? – Bruce

+0

Chubsdad sí ... –

8

Chusbad proporcionó una explicación en profundidad que implica la norma, voy a tratar de dar una explicación accesible.

En C++, hay 3 especificadores de nivel de acceso: public, protected y private. Estos deben determinar quién puede acceder a métodos, atributos o clases base. Es típico entre los lenguajes orientados a objetos.

Aquí elegiste private herencia. Conceptualmente esto significa que usted busca OCULTAR el hecho de que Derived hereda de Base a personas externas, lo que generalmente significa que se trata de detalles de implementación.

Como consecuencia, el "exterior" no tiene conocimiento de esta relación. Esto es impuesto por el compilador con este mensaje inaccessible.

Desde un punto de vista de diseño, generalmente no se requiere la herencia private. O bien se aplica el Principio de sustitución de Liskov y utiliza la herencia public, ya sea un detalle de implementación y usa composición.

0

esto da el error C2243: 'tipo de conversión': la conversión de 'derivado *' a 'base *' existe, pero es inaccesible Esta clase derivada se ha heredado en privado. Así, el objeto de clase base no se crea cuando se obtiene la creación sucede. para crear las primeras llamadas del objeto derivado va a crear el objeto de la clase base que no está sucediendo. solución es derivar la clase públicamente. no importa si usa palabras clave virtuales con funciones miembro o no.

Cuestiones relacionadas