2010-05-29 150 views
14

如何用C++创建一个抽象类,并使用一些我想在子类中重写的抽象方法? .h文件应该怎么看?有没有.cpp,如果是这样,它应该看起来如何?C++:用抽象方法创建抽象类并重写子类中的方法

在Java中它是这样的:

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

翻译这段代码C++是对我来说足够。

编辑:

我创建的代码,但是当我尝试遍历对象我得到以下错误:

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 

有了这个代码:

vector<GameObject> gameObjects; 

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

你的“在我的游戏循环”代码是......不完整,至多。什么是“对象”?如果你还没有,我强烈建议从[The Definitive C++ Book Guide and List]获得一本初学者书籍(http://stackoverflow.com/questions/388242/the-definitive-c-book-guide -and列表)。 – 2010-05-29 22:54:37

+0

您也可以咨询Herb Sutter的文章[虚拟性](http://www.gotw.ca/publications/mill18。htm),其中讨论了在C++中使用虚函数和继承时的许多最佳实践。 – 2010-05-29 22:59:53

回答

20

在Java中,默认情况下所有方法都是virtual,除非您声明它们为final。在C++中,这是相反的:你需要明确声明你的方法virtual。为了使它们成为纯虚拟的,你需要将它们初始化为0 :-)如果你的类中有一个纯虚拟方法,它会自动变成抽象的 - 没有明确的关键字。

在C++中,您应该(几乎)总是为您的基类virtual定义析构函数,以避免棘手的资源泄漏。所以我添加了下面的例子:

// 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

你可以看看我的编辑吗? – 2010-05-30 15:15:52

+2

@Martijn,你不能有一个'vector ',因为它会按值存储它的元素,但是'GameObject'是抽象的,可以没有实例。您需要一个'vector '或最好是一个'vector >'来存储多态对象。另请参阅James McNellis的回答。 – 2010-05-30 15:31:01

+0

为什么你需要在GameObject.h中声明方法,如果它们已经声明的话? – HasaDev 2016-09-13 19:55:08

6

成员函数需要在基类中声明为virtual。在Java中,成员函数默认是虚拟的;他们不在C++中。

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

virtual使虚拟成员函数; = 0使纯虚拟成员函数。这个类也是抽象的,因为它至少有一个虚拟成员函数没有具体的最终覆盖。

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

如果一个成员函数声明在基类虚拟的,它是在任何派生类自动虚拟(你可以把virtual在声明:

在派生类(ES)

然后派生类,如果你愿意,但它是可选的)。

+0

我可以为GameObject的向量中的每个元素调用'update();'吗? – 2010-05-29 22:54:22

+0

不需要。您需要一个GameObject *或像shared_ptr或auto_ptr这样的相关类的向量。 – Puppy 2010-05-30 11:15:42

+0

是的,但这是暗示'GameObject'是抽象的。 – 2010-05-30 13:51:26

4

在C++中使用关键字虚拟您的程序,并指定=0;放进去。像这样:

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

} 

虚拟方法的0分配给它自动使您的类抽象。