2010-05-06 14 views
5

Ich bin ein einfaches Konsolenspiel in C machen ++Zugriff auf abgeleitete Klassen Mitglieder mit einer Basisklasse Zeiger

würde ich gerne wissen, ob ich Mitglieder aus der ‚entPlayer‘ Klasse zugreifen kann, während einen Zeiger verwenden, die auf das Verzeichnis ist Basisklasse ('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; 
} 

Wie würde ich in der Lage sein ply- nennen> setName etc?

ODER

Wenn es nicht möglich, auf diese Weise, was wäre ein besserer Weg?

+1

Entschuldigung, ich musste Ihre Codeformatierung bearbeiten. Die leeren Zeilen haben deinen Code wirklich groß gemacht! Noch ein kleiner Kommentar zu deinem Code: halte dich an eine konsistente Namenskonvention, z. AllClassNamesLikeThis und parameter_names_like_this. Noch eine Nite: Sie werden sich später mit Abkürzungen wie "ent" in den Hintern treten. Ich kann ehrlich nicht sagen, was ein EntPlayer sein soll. Ich denke, was du meinst, ist nur "Spieler", oder wenn du dich "PlayerEntity" fühlst. – allyourcode

Antwort

11

Es ist möglich, mit einem Cast. Wenn Sie wissen, für eine Tatsache, dass die Basisklasse Zeiger auf ein Objekt der abgeleiteten Klasse, können Sie static_cast:

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

Wenn Sie nicht sicher wissen Sie, dann müssen Sie dynamic_cast und testen die Ergebnis zu sehen, dass es nicht null ist. Beachten Sie, dass Sie dynamic_cast nur verwenden können, wenn die Basisklasse mindestens eine virtuelle Funktion besitzt. Ein Beispiel:

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

Das heißt, es wäre viel besser, Ihre Klasse die Funktionalität unter Verwendung von Polymorphismus zu verkapseln (das heißt virtuelle Funktionen).

Apropos virtuellen Funktionen, hat Ihre Klassenhierarchie als implementieren undefiniertes Verhalten: Sie können ein Objekt eines abgeleiteten Typs nur über einen Zeiger auf eine seiner Basisklassen löschen, wenn die Basisklasse als virtueller Destruktor. Daher müssen Sie der Basisklasse einen virtuellen Destruktor hinzufügen.

+0

Ich hatte eine verwandte Frage, auf die diese Antwort antwortet: D Was ich wissen wollte, war: "Wie kann ich feststellen, ob mein Basiszeiger tatsächlich auf ein abgeleitetes Objekt zeigt?".Die Antwort, die ich lese, ist die Verwendung von dynamic_cast (funktioniert nur, wenn die Basisklasse eine virtuelle Funktion hat). Dann sehen Sie, ob das Ergebnis NULL ist. #victorybaby – allyourcode

+0

Dies beantwortet (teilweise) auch eine andere Frage, die ich schon seit einiger Zeit zu C++ habe: Was ist der Unterschied zwischen den verschiedenen Arten von Güssen? Es scheint sicher eine gute Anzahl von ihnen zu sein! – allyourcode

0

Sie können eine dynamische Umwandlung tun:

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

Dies wird (falls erfolgreich) in einem abgeleiteten Zeiger führen.

Andernfalls wird NULL zurückgegeben.

1

Ich würde so etwas wie dies zu tun:

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++ macht, was Sie wirklich ungeschickt versuchen zu tun, denn das ist wahrscheinlich nicht das, was Sie tun sollten, und es wird versucht, Sie zu gut führen objektorientiertes Design. In der Tat, standardmäßig compilers often disable run-time type information (RTTI), die benötigt wird, um dynamic_cast arbeiten zu lassen.

Ohne Ihren Kontext zu kennen, ist es schwer zu sagen, was Sie stattdessen tun sollten. Was ich sagen kann ist, dass, wenn Sie einen spezifischeren Zeiger wollten, sollten Sie einen Ring darauf setzen, sollten Sie fast sicher keine Funktion verwenden, die Entity* zurückgibt, und es gibt wahrscheinlich einen besseren Ansatz.

Verwandte Themen