2010-05-06 15 views
5

Sto facendo un semplice gioco per console in C++i membri della classe Accesso ai derivati ​​con un puntatore alla classe base

Vorrei sapere se posso accedere ai membri della classe 'entPlayer' mentre si utilizza un puntatore che punta al classe base ("Entity"):

class Entity { 
public: 
    void setId(int id) { Id = id; } 
    int getId() { return Id; } 
protected: 
    int Id; 
}; 

class entPlayer : public Entity { 
    string Name; 
public: 
    void setName(string name) { Name = name; } 
    string getName() { return Name; } 
}; 

Entity *createEntity(string Type) { 
    Entity *Ent = NULL; 
    if (Type == "player") { 
     Ent = new entPlayer; 
    } 
    return Ent; 
} 

void main() { 
    Entity *ply = createEntity("player"); 
    ply->setName("Test"); 
    ply->setId(1); 

    cout << ply->getName() << endl; 
    cout << ply->getId() << endl; 

    delete ply; 
} 

Come potrei chiamare ply-> setName ecc?

O

Se non è possibile in questo modo, che cosa sarebbe un modo migliore?

+1

Siamo spiacenti, ho dovuto modificare la formattazione del codice. Le righe vuote hanno reso il tuo codice davvero alto! Un altro piccolo commento sul tuo codice: segui una convenzione di denominazione coerente, ad es. AllClassNamesLikeThis e parameter_names_like_this. Un altro pidocchio: ti prenderai a calci nel sedere più tardi con abbreviazioni come "ent". Onestamente non posso dire cosa dovrebbe essere un entPlayer. Penso che quello che intendi sia solo "Giocatore", o se ti senti verboso "PlayerEntity". – allyourcode

risposta

11

È possibile utilizzare un cast. Se si sa per certo che i punti di puntatore alla classe base a un oggetto della classe derivata, è possibile utilizzare static_cast:

Entity* e = /* a pointer to an entPlayer object */; 
entPlayer* p = static_cast<entPlayer*>(e); 
p->setName("Test"); 

Se non si sa per certo, allora avete bisogno di utilizzare e testare il dynamic_cast risultato di vedere che non è nullo. Si noti che è possibile utilizzare solo dynamic_cast se la classe base ha almeno una funzione virtuale. Un esempio:

Entity* e = /* a pointer to some entity */; 
entPlayer* p = dynamic_cast<entPlayer*>(e); 
if (p) 
{ 
    p->setName("Test"); 
} 

Detto questo, sarebbe di gran lunga migliore per incapsulare le funzionalità del tuo classe utilizzando il polimorfismo (vale a dire le funzioni virtuali).

Parlando di funzioni virtuali, la gerarchia di classi come strumento ha un comportamento non definito: è possibile eliminare un oggetto di un tipo derivato solo tramite un puntatore a una delle sue classi di base se la classe di base è un distruttore virtuale. Quindi, è necessario aggiungere un distruttore virtuale alla classe base.

+0

Ho una domanda correlata, a cui questa risposta risponde: D Quello che volevo sapere era "Come posso sapere se il mio puntatore di base punta effettivamente su un oggetto derivato?".La risposta che sto spigolando è usare dynamic_cast (funziona solo se la classe base ha una funzione virtuale). Quindi, controlla se il risultato è NULL. #victorybaby – allyourcode

+0

Anche questo (parzialmente) risponde a un'altra domanda che ho avuto per un po 'su C++: Qual è la differenza tra i vari tipi di cast? Di sicuro sembra che ce ne siano un buon numero! – allyourcode

0

Si può fare un cast dinamico:

entPlayer * pPlayer = dynamic_cast<entPlayer *>(pointer_to_base); 

Questo (in caso di successo) comportare un puntatore derivato.

Altrimenti viene restituito NULL.

1

vorrei prendere in considerazione facendo qualcosa di simile:

public: 
void setId(int id) 
{ 

    Id = id; 

} 

void virtual setName(string name) = 0; // Virtual Function 
string virtual getName() = 0; // Virtual Function 

int getId() { return Id; } 

protected: 
    int Id; 

}; 

class entPlayer : public Entity { 

    string Name; 

public: 
    entPlayer() { 

     Name = ""; 
     Id = 0; 

    } 

    void entPlayer::setName(string name) { // Must define function 

     Name = name; 
} 

string entPlayer::getName() { return Name; } // again must define function here 

}; 
0

C++ fa ciò che si sta cercando di fare davvero imbarazzante, perché questo non è probabilmente quello che si dovrebbe fare, e sta cercando di voi portare a buon design orientato agli oggetti. Di fatto, per impostazione predefinita, compilers often disable run-time type information (RTTI), che è necessario per far funzionare dynamic_cast.

Senza conoscere il tuo contesto più ampio, è difficile dire cosa invece dovresti fare. Quello che posso dire è che se si voleva un puntatore più specifico, si dovrebbe aver messo un anello su di esso quasi certamente non si dovrebbe usare una funzione che restituisce un Entity*, e c'è probabilmente un approccio migliore.

Problemi correlati