2015-06-01 19 views
5

Sono un novizio in C++. Qualcuno può dirmi perché il seguente codice sorgente funziona bene?Accesso ai membri della classe dopo il cast del puntatore in C++

#include <iostream> 

using namespace std; 

class A{ 
public: 
    A(){ cout << "create a" << endl; } 
    void sayGoodbye() { cout << "goodbye" << endl; } 
}; 

class B{ 
public: 
    B() { cout << "create b" << endl; } 
    void sayHello() { cout << "hello" << endl; } 
}; 

int main(array<System::String ^> ^args) 
{ 
    A* a = new A(); 

    ((B*)a)->sayHello(); 
    a->sayGoodbye(); 

    return 0; 
} 

uscita:

create a 
hello 
goodbye 

Quello che mi chiedo è per questo che può l'accesso B :: sayHello proprio gettando in questo modo? Può accedere a tutti i membri pubblici di qualsiasi classe in questo modo?

risposta

4

Sì, è possibile.

Ma no, non è possibile.

Quando si utilizza un cast in stile C in questo modo, si promette al computer che si sa cosa si sta facendo e che il cast è valido. Quando è valido per, stai bene. Quando non lo è, è l'errore.

In questo caso, non è, ed è colpa tua.

Ora, puoi chiedere perché "funziona bene", ma questo è un caso: è pura casualità. Una volta che il programma è stato compilato, andrà in crash o ucciderà i tuoi figliastri se accederai letteralmente alla memoria non valida. In questo caso particolare, non stai accedendo alla memoria non valida.

Non significa che tu abbia ragione, però.

Non farlo.

+1

Le prime due frasi sono molto precise. Descrivono molto bene i linguaggi C/C++. Mi piace. – dlask

0

Poiché le funzioni definite per le classi A e B non dipendono da alcun dato archiviato in tali classi, il computer non deve leggere nulla per eseguire le funzioni e sono in grado di eseguire.

In generale, tuttavia, se il metodo sayHello è necessario per leggere i dati memorizzati nella classe B, il cast risulterebbe in un errore di seg o altri problemi gravi, poiché ciò renderebbe il computer in grado di leggere in memoria. detto è assegnato per adattarsi a un oggetto di tipo B, che non è il caso poiché l'oggetto è di tipo A.

0

say Il metodo Hello non sta accedendo a nessun membro di dati dalla classe B. Inoltre, ((B*)a)->sayHello(); è compilato per qualcosa come call- to-mangled-sayHello-member-function-of-B (questo). Quindi, la funzione membro della classe B dice che Hello verrà invocato passando un puntatore a un oggetto di B e quel puntatore non viene utilizzato all'interno del metodo sayHello. Quindi funzionerà in questo caso.

((B*)0)->sayHello(); 
((B*)1)->sayHello(); 
((B*)2)->sayHello(); 

In effetti tutte le chiamate sopra funzioneranno. sayHello riceverà un puntatore con l'indirizzo 0, 1, 2. Come direHello non sta accedendo a nessun membro di dati di B, quindi funzioneranno. Se sayHello accede a membri di dati non statici, si verificherà un grosso arresto anomalo. Generalmente, il comportamento non è definito. Se sayHello è virtuale, allora ci saranno problemi reali. Perché in questo caso sarà necessario un oggetto valido in memoria per risolvere la funzione chiamata in fase di esecuzione.

2

This non è una risposta alla tua domanda, ma può dare più conoscenza e opzioni quando si lavora con il puntatore del casting:

È possibile vedere diverse tecniche di fusione come segue:

static_cast 
dynamic_cast 
const_cast 
reinterpret_cast 
C-style cast (type)value 
Function-style cast type(value) 
1

Nella mia caso, io uso dynamic_cast per verificare questo problema di trasmissione. E anche utile in caso di down-casting. Ma abbiamo un problema con dynamic_cast nel down-casting è che dobbiamo avere un tipo di classe polimorfo.

Problemi correlati