2010-05-29 69 views
14

Làm thế nào để tạo trong C++ một lớp trừu tượng với một số phương thức trừu tượng mà tôi muốn ghi đè trong một lớp con? Giao diện tệp .h như thế nào? Có .cpp không, nếu có thì trông như thế nào?C++: Tạo lớp trừu tượng với phương thức trừu tượng và ghi đè phương thức trong lớp con

Trong Java nó sẽ trông như thế này:

abstract class GameObject 
{ 
    public abstract void update(); 
    public abstract void paint(Graphics g); 
} 

class Player extends GameObject 
{ 
    @Override 
    public void update() 
    { 
     // ... 
    } 

    @Override 
    public void paint(Graphics g) 
    { 
     // ... 
    } 

} 

// In my game loop: 
List<GameObject> objects = new ArrayList<GameObject>(); 
for (int i = 0; i < objects.size(); i++) 
{ 
    objects.get(i).update(); 
} 
for (int i = 0; i < objects.size(); i++) 
{ 
    objects.get(i).paint(g); 
} 

dịch mã này vào C++ là đủ cho tôi.

Edit:

Tôi tạo ra mã nhưng khi tôi cố gắng để lặp qua các đối tượng tôi nhận được lỗi sau:

Game.cpp:17: error: cannot allocate an object of abstract type ‘GameObject’ 
GameObject.h:13: note: because the following virtual functions are pure within ‘GameObject’: 
GameObject.h:18: note:   virtual void GameObject::Update() 
GameObject.h:19: note:   virtual void GameObject::Render(SDL_Surface*) 
Game.cpp:17: error: cannot allocate an object of abstract type ‘GameObject’ 
GameObject.h:13: note: since type ‘GameObject’ has pure virtual functions 
Game.cpp:17: error: cannot declare variable ‘go’ to be of abstract type ‘GameObject’ 
GameObject.h:13: note: since type ‘GameObject’ has pure virtual functions 

Với mã này:

vector<GameObject> gameObjects; 

for (int i = 0; i < gameObjects.size(); i++) { 
    GameObject go = (GameObject) gameObjects.at(i); 
    go.Update(); 
} 
+0

Mã "trong vòng trò chơi của tôi" ... không đầy đủ, tốt nhất. 'Đối tượng' là gì? Nếu bạn chưa có, tôi khuyên bạn nên lấy một trong những cuốn sách mới bắt đầu từ [Sách hướng dẫn và sách định nghĩa C++ Definitive] (http://stackoverflow.com/questions/388242/the-definitive-c-book-guide -và danh sách). –

+0

Bạn cũng có thể tham khảo bài viết của Herb Sutter, [Virtuality] (http://www.gotw.ca/publications/mill18).htm), thảo luận về nhiều thực tiễn tốt nhất khi sử dụng các hàm ảo và thừa kế trong C++. –

Trả lời

20

Trong Java, tất cả các phương pháp là virtual theo mặc định, trừ khi bạn khai báo chúng final. Trong C++ nó là cách khác xung quanh: bạn cần khai báo rõ ràng các phương thức của bạn virtual. Và để làm cho chúng tinh khiết ảo, bạn cần phải "khởi tạo" chúng thành 0 :-) Nếu bạn có một phương pháp ảo thuần túy trong lớp của bạn, nó sẽ tự động trở thành trừu tượng - không có từ khóa rõ ràng cho nó.

Trong C++ bạn nên (hầu như) luôn xác định hàm hủy cho các lớp cơ sở của bạn virtual, để tránh rò rỉ tài nguyên phức tạp. Vì vậy, tôi nói thêm rằng để ví dụ dưới đây:

// GameObject.h 

class GameObject 
{ 
public: 
    virtual void update() = 0; 
    virtual void paint(Graphics g) = 0; 
    virtual ~GameObject() {} 
} 

// Player.h 
#include "GameObject.h" 

class Player: public GameObject 
{ 
public: 
    void update(); 

    void paint(Graphics g); 
} 

// Player.cpp 
#include "Player.h" 

void Player::update() 
{ 
    // ... 
} 

void Player::paint(Graphics g) 
{ 
    // ... 
} 
+0

Bạn có thể kiểm tra chỉnh sửa của tôi không? –

+2

@Martijn, bạn không thể có 'vector ' vì điều đó sẽ lưu trữ các phần tử của nó theo giá trị, nhưng 'GameObject', trừu tượng, không thể có trường hợp. Bạn cần 'vector ' hoặc tốt hơn là 'vector >' để lưu trữ các đối tượng đa hình. Xem thêm các bình luận cho câu trả lời của James McNellis. –

+0

Tại sao bạn cần khai báo các phương thức trong GameObject.h, nếu chúng đã được khai báo? – HasaDev

6

Thành viên các hàm cần được khai báo virtual trong lớp cơ sở. Trong Java, các hàm thành viên là ảo theo mặc định; chúng không có trong C++.

class GameObject 
{ 
public: 
    virtual void update() = 0; 
    virtual void paint(Graphics g) = 0; 
} 

virtual tạo thành một hàm thành viên ảo; các = 0 làm cho một thành viên chức năng tinh khiết ảo. Lớp này cũng trừu tượng vì nó có ít nhất một hàm thành viên ảo không có trọng số cuối cùng cụ thể.

Sau đó, trong lớp học của bạn có nguồn gốc (es):

class Player : public GameObject 
{ 
public: 
    void update() { }   // overrides void GameObject::update() 
    void paint(Graphics g) { } // overrides void GameObject::paint(Graphics) 
} 

Nếu một hàm thành viên được khai báo ảo trong một lớp cơ sở, đó là tự động ảo trong bất kỳ lớp được thừa kế (bạn có thể đặt virtual trong khai báo trong nếu bạn muốn, nhưng đó là tùy chọn).

+0

Và tôi có thể gọi 'update();' cho mỗi phần tử trong vectơ của GameObject không? –

+0

Không. Bạn cần một véc tơ của GameObject * hoặc một lớp liên quan như shared_ptr hoặc auto_ptr. – Puppy

+0

Có, nhưng điều đó được ngụ ý bởi thực tế là 'GameObject' là trừu tượng. –

4

Trong C++ bạn sử dụng từ khóa ảo trên thói quen của bạn, và gán =0; vào chúng. Giống như vậy:

class GameObject { 
public: 
    virtual void update()=0; 
    virtual void paint(Graphics g)=0; 

} 

Có phương pháp ảo được tự động làm cho lớp trừu tượng của bạn.

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