2010-05-06 103 views
5

Tôi đang tạo một trò chơi giao diện điều khiển đơn giản trong C++Truy cập các thành viên lớp dẫn xuất bằng một con trỏ lớp cơ sở

Tôi muốn biết liệu mình có thể truy cập các thành viên từ lớp 'entPlayer' hay không lớp cơ sở ('Thực thể'):

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; 
} 

Làm cách nào để có thể gọi ply-> setName etc?

HOẶC

Nếu không thể như vậy, cách nào tốt hơn?

+1

Rất tiếc, tôi phải chỉnh sửa định dạng mã của bạn. Các dòng trống làm cho mã của bạn thực sự cao! Một nhận xét nhỏ khác về mã của bạn: gắn với quy ước đặt tên nhất quán, ví dụ: AllClassNamesLikeThis và parameter_names_like_this. Một nit khác: bạn sẽ đá vào mông sau với chữ viết tắt như "ent". Tôi thành thật không thể nói những gì một entPlayer được cho là. Tôi nghĩ những gì bạn có nghĩa là chỉ là "Player", hoặc nếu bạn đang cảm thấy tiết "PlayerEntity". – allyourcode

Trả lời

11

Có thể sử dụng dàn diễn viên. Nếu bạn biết một thực tế rằng các điểm con trỏ lớp cơ sở để một đối tượng của lớp được thừa kế, bạn có thể sử dụng static_cast:

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

Nếu bạn không biết chắc chắn, sau đó bạn cần phải sử dụng dynamic_cast và kiểm tra kết quả để thấy rằng nó không phải là null. Lưu ý rằng bạn chỉ có thể sử dụng dynamic_cast nếu lớp cơ sở có ít nhất một hàm ảo. Ví dụ:

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

Điều đó sẽ tốt hơn nếu đóng gói chức năng của lớp bằng tính đa hình (tức là chức năng ảo).

Phát biểu của các chức năng ảo, phân cấp lớp của bạn khi thực hiện có hành vi không xác định: bạn chỉ có thể xóa đối tượng của một loại có nguồn gốc thông qua con trỏ đến một trong các lớp cơ sở của nó nếu lớp cơ sở là trình phá hủy ảo. Vì vậy, bạn cần thêm một destructor ảo vào lớp cơ sở.

+0

Tôi có một câu hỏi liên quan, câu trả lời này trả lời: D Điều tôi muốn biết là "Làm cách nào để biết liệu con trỏ cơ sở của tôi có thực sự trỏ đến một đối tượng có nguồn gốc không?".Câu trả lời mà tôi đang lượm lặt là sử dụng dynamic_cast (chỉ hoạt động nếu lớp cơ sở có một hàm ảo). Sau đó, xem kết quả là NULL. #victorybaby – allyourcode

+0

Điều này cũng (một phần) trả lời một câu hỏi khác mà tôi đã có một thời gian về C++: sự khác biệt giữa các loại phôi khác nhau là gì? Có chắc chắn có vẻ là một số lượng tốt của họ! – allyourcode

0

Bạn có thể làm một diễn viên năng động:

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

này sẽ (nếu thành công) dẫn đến một con trỏ có nguồn gốc.

Nếu không NULL được trả lại.

1

tôi sẽ xem xét làm một cái gì đó như thế này:

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++ làm cho những gì bạn đang cố gắng làm thật sự lúng túng, bởi vì điều này có lẽ không phải là điều bạn nên làm, và nó đang cố gắng để dẫn bạn đến tốt thiết kế hướng đối tượng. Thực tế, theo mặc định, compilers often disable run-time type information (RTTI), cần thiết để thực hiện công việc dynamic_cast.

Không biết bối cảnh rộng hơn của bạn, thật khó để nói bạn nên làm gì thay thế. Những gì tôi có thể nói là nếu bạn muốn có một con trỏ cụ thể hơn, bạn nên đặt một chiếc nhẫn lên đó bạn gần như chắc chắn không nên sử dụng một hàm trả về một số Entity* và có thể có cách tiếp cận tốt hơn.

Các vấn đề liên quan