Perché la conversione tra * derivato a base di * non riesce con l'ereditarietà privata?
-
01-10-2019 - |
Domanda
Ecco il mio codice -
#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;
}
Questo dà un errore di tempo di compilazione.
error: 'base' is an inaccessible base of 'derived'
Dato che il compilatore cercherà di chiamare la classe di base sid()
perché ottengo questo errore? Qualcuno può spiegare questo.
Soluzione
$ 11.2 / 4 stati -
Una classe base B di N è accessibile a R, se
- un membro pubblico inventata di B sarebbe un membro pubblico di N, o
- R si verifica in un membro o un amico della classe N, e un pubblico inventato membro del B sarebbe un privato o membro protetto di N, o
- R si verifica in un organo o amico di una classe P derivata da N, e un membro pubblico inventato di B sarebbe un membro privato o protetto di P, o
- esiste una classe S tale che B è una classe base di S accessibile a R e S è una classe base di N accessibili a R ".
Qui 'B' è 'base', 'N' è 'derivato' e 'R' è principale.
-
Si consideri il secondo proiettile 'R si verifica in un membro o un amico di una classe N, ...'. Questa clausola non si applica come 'R' (principale) non è né un membro né amico di 'N' (Derivato)
-
Si consideri il terzo proiettile 'R si verifica in un membro o un amico di una classe P ....'. Questo Natale anche non si applica per gli stessi motivi di cui sopra
-
Si consideri il quarto proiettile Ancora una volta questa clausola non si applica
Quindi possiamo concludere che 'Base' non è una classe accessibile di 'derivata'.
$ 11.2 / 5 stati -
Se una classe base è accessibile, si può convertire implicitamente un puntatore a una classe derivata a un puntatore a tale classe base (4,10, 4.11). [Nota: ne consegue che i membri e gli amici di una classe X può implicitamente convertire un X * a un puntatore ad un privato o protetto immediato classe base di X. -end nota]
Dato Base
non è una classe accessibile di Derived
quando vi si accede in main
, la conversione standard dalla classe derivata alla classe base è mal formata. Quindi l'errore.
EDIT 2:
di studio i messaggi di errore di alcuni compilatori popolari e che dovrebbe aiutare a ottenere una migliore comprensione. Nota come la parola 'inaccessibile' si apre così frequentemente e costantemente in tutti i messaggi di errore
I riferimenti sono dalla N3000 progetto di norma. Devo ancora scaricare l'ultima bozza:)
GCC prog.cpp: In funzione ‘int main ()’: prog.cpp: 27: errore:‘base’è una base inaccessibile di ‘deriva’
Comeau Online "ComeauTest.c", linea 26: errore: la conversione a base di inaccessibile classe "base" non è permesso PTR = new derivati;
VS2010 errore C2243: 'cast di tipo': conversione da 'deriva *' a 'base *' Esiste, ma è inaccessibile
Altri suggerimenti
Ho il sospetto che il problema è che non è possibile convertire un puntatore derivato a un puntatore di base, come l'eredità è privato.
Chusbad fornito una spiegazione approfondita che coinvolge lo standard, cercherò di fornire una spiegazione accessibile.
In C ++, ci sono 3 prescrittori Livello di accesso: public
, protected
e private
. Quelli sono destinati a determinare chi può accedere ai metodi, attributi o classi di base. E 'tipico tra linguaggi Object Oriented.
Qui, eletto eredità private
. Concettualmente questo significa che si cercano di nascondere il fatto che eredita da Derived
Base
verso terzi, il che significa in genere questo è un dettagli di implementazione.
Di conseguenza, il "esterno" non è a conoscenza di questo rapporto. Questo viene applicata dal compilatore con questo messaggio inaccessible
.
Da un punto di vista del design, private
eredità non è generalmente richiesto. O il principio di sostituzione Liskov si applica e si utilizza l'ereditarietà public
, o si tratta di un dettaglio di implementazione e si utilizza la composizione.
Lo sai che eredita da class derived
class base
, ma la funzione main()
non lo sa. La ragione per cui la funzione main()
non sa è che hai fatto class derived
ereditare privatamente da class base
.
Quindi, quando si tenta di assegnare ai new derived
ptr
, i tipi di puntatore non sono compatibili.
Prova questo:
#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;
}
questo dà l'errore C2243: 'cast di tipo': conversione da 'derivato *' a 'base *' esiste, ma non è accessibile Questa classe derivata è stato ereditato privatamente .so oggetto classe di base non viene creata quando la creazione get derieved accade. per creare l'oggetto derivano primi inviti va a creare l'oggetto classe base che non accada. soltuion è derivare la classe pubblicamente. esso doesnt importa se la vostra utilizzando parola chiave virtuale con funzioni membro o meno.
È necessario dichiarare la funzione sid () nella classe base come virtuale. Una funzione virtuale può essere sostituita da una classe derivata. In caso contrario, si sarebbe probabilmente ottenere un errore di compilazione.