Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ I';我试图[用C+;+;]实践多态性和OOD原则。需要指导和回答几个问题吗_C++_Oop_Polymorphism_Sdl_Virtual Functions - Fatal编程技术网

C++ I';我试图[用C+;+;]实践多态性和OOD原则。需要指导和回答几个问题吗

C++ I';我试图[用C+;+;]实践多态性和OOD原则。需要指导和回答几个问题吗,c++,oop,polymorphism,sdl,virtual-functions,C++,Oop,Polymorphism,Sdl,Virtual Functions,我正在写一个简单的2D游戏,以带有RPG元素的迷宫为中心。主要是为了学习目的,练习课堂设计、图论算法、数据结构使用和2D图形的使用 课程简介: 游戏本身是基于瓷砖的。它目前在屏幕上生成并绘制迷宫,允许玩家移动,并对墙壁进行碰撞检测;此外,它还可以处理较大迷宫的屏幕滚动 不管怎样,现在我正在构建一个对象,它处理在地图周围放置对象。首先是金币,然后是红心和物品。我认为现在是练习继承和多态性的好时机,但我还没有接受过这种设计的正式培训。以下是头文件: #ifndef MAP_OBJECT_H #def

我正在写一个简单的2D游戏,以带有RPG元素的迷宫为中心。主要是为了学习目的,练习课堂设计、图论算法、数据结构使用和2D图形的使用

课程简介:

游戏本身是基于瓷砖的。它目前在屏幕上生成并绘制迷宫,允许玩家移动,并对墙壁进行碰撞检测;此外,它还可以处理较大迷宫的屏幕滚动

不管怎样,现在我正在构建一个对象,它处理在地图周围放置对象。首先是金币,然后是红心和物品。我认为现在是练习继承和多态性的好时机,但我还没有接受过这种设计的正式培训。以下是头文件:

#ifndef MAP_OBJECT_H
#define MAP_OBJECT_H

#include "Common.h"
#include "Utility Functions.h"

const int TILE_SIZE = 80;

class MapObject
{
public:


    MapObject(unsigned int nClips, unsigned int r, unsigned int c, unsigned int cSize)     :
         sheet(0), clips(0), row(r), col(c), numClips(nClips), clipSize(cSize)
    {
        //For those of you who aren't familiar with sprite sheet usage, basically this
        // handles which part of the sprite sheet your on, so it will draw the correct sprite to the screen
        if(numClips > 0) clips = new SDL_Rect[numClips];
        box.h = clipSize;
        box.w = clipSize;
    }

    virtual ~MapObject()  //NOt sure if this is right.  All the derived classes will
                          // behave the same upon deletion, since the only resource 
                          //  that got allocated was for the box SDL_rect
    {
        if(clips) delete[] clips;
    }


    void initBox(int modX, int modY);
    //I think each object will draw a little different, so I made it virtual
    virtual void draw() = 0;
    //Same with interaction--although I'm not sure how my player class is going to be able to handle this yet
    virtual void interact() = 0;

     SDL_Rect getBox() const;

 private:
    SDL_Surface*  sheet;
    SDL_Rect      box;
    SDL_Rect*     clips;
    unsigned int  row, col;
    unsigned int  numClips;
    unsigned int  clipSize;

     MapObject() {}  //Made this private because I want the memory to be allocated, and 
                     // numClips needs to be initialized for that to happen, so 
                     //basically I'm forcing the user to use the constructor with parameters
};


class Coin : public MapObject
{
    enum  CoinFace  //This represents all the different coin facings in the sprite 
                     //sheet, so that is can animate.  Used in the draw function.
    {
        FRONT,
        TURN1,
        TURN2,
        TURN3,
        USED
    };

    CoinFace  active;

public:
    virtual void draw(SDL_Surface* destination);
    virtual void interact();
};

#endif //MAP_OBJECTS
我最大的问题是一个一般性的问题:这是我设计的一个良好开端吗?他们的问题突出吗?OOD原则/惯例的滥用

这样定义虚拟析构函数会允许所有派生类使用它吗?或者我需要为每个派生类定义它吗

我意识到这是很多,我感谢任何帮助。我真的在努力理解OOD以及如何使用多态性,所以来自一些专业人士的帮助将非常有用

再次感谢


编辑:我还有一个大问题,就是如何开始修改派生类中的私有数据成员。我听说如果我需要这样做的话,那是糟糕的类设计,我想我不知道如何编写一个好的接口。

问题的一部分取决于观点。然而:

  • 我在这里只能说,你的方法是可行的,而且你正在朝着这个方向努力。只是别忘了定义Coin的构造函数
  • 虚拟析构函数的全部用途是在只有基类类型的指针时调用适当的析构函数。此外,派生析构函数在自动调用基析构函数之前执行,而无需显式调用它。在这种情况下,由
    MapObject*
    指向的硬币将通过
    delete
    正确销毁,该操作按以下顺序执行
    ~Coin()
    ~MapObject()
  • 这个问题很容易演变成关于正确接口构造的辩论,但以下是一些解决方案:
    • 通过构造函数定义私有成员,防止它们被其他类修改
    • 将成员设置为基类
      受保护的
      ,而不是
      私有的
      。对于您希望在此处执行的操作,这可能是更简单的解决方案
    • 为私有成员类型创建setter,如
      setActive(CoinFace)
      。您可以根据需要调整这些函数,例如防止属性的无效定义导致整个对象不一致。与前面的解决方案一样,您可以保护这些setter,以便只有派生类才能访问它们
    • 让a类成为另一类的朋友(称之为a)。的实例可以获取该类的对象并访问其所有私有成员

  • 问题的一部分取决于意见。然而:

  • 我在这里只能说,你的方法是可行的,而且你正在朝着这个方向努力。只是别忘了定义Coin的构造函数
  • 虚拟析构函数的全部用途是在只有基类类型的指针时调用适当的析构函数。此外,派生析构函数在自动调用基析构函数之前执行,而无需显式调用它。在这种情况下,由
    MapObject*
    指向的硬币将通过
    delete
    正确销毁,该操作按以下顺序执行
    ~Coin()
    ~MapObject()
  • 这个问题很容易演变成关于正确接口构造的辩论,但以下是一些解决方案:
    • 通过构造函数定义私有成员,防止它们被其他类修改
    • 将成员设置为基类
      受保护的
      ,而不是
      私有的
      。对于您希望在此处执行的操作,这可能是更简单的解决方案
    • 为私有成员类型创建setter,如
      setActive(CoinFace)
      。您可以根据需要调整这些函数,例如防止属性的无效定义导致整个对象不一致。与前面的解决方案一样,您可以保护这些setter,以便只有派生类才能访问它们
    • 让a类成为另一类的朋友(称之为a)。的实例可以获取该类的对象并访问其所有私有成员

  • 我在某个地方读到,将数据成员置于受保护状态以便派生类可以访问它们是一种不好的做法。似乎每件事都有二传手也有点草率。您对此有何具体意见??你说的“根据我的需要调整setter”到底是什么意思?我不确定两个二传手在不同的班级之间会有什么变化。也非常感谢你的回答,它非常有帮助!不管许多人怎么说,受保护的成员是许多其他人的解决方案。我所说的调整是指在设置成员时应用限制或其他操作。我不是指动态函数。例如,
    Coin::setActive(CoinFace)
    可以阻止任何人将active设置为USED。这是一个控制物体的问题。在我看来,当派生类需要修改上层的内容时,setter是最好的解决方案。您应该使这些代码层尽可能独立,以减少对setter的需求。让setter受到保护并将数据留给我怎么样