草庐IT

c++ - 在父类中访问子类的功能

coder 2024-02-22 原文

我一直在编写一个简单的棋盘游戏,以在实践中学习 C++ 的概念。我已经实现了板:它由图 block 组成,每个图 block 都是从父类继承的子类。棋盘是一个具有图 block vector 的类。

瓷砖有几种。其中一些可以由玩家购买。有几种不同类型的可购买瓷砖以及不同的属性,所以我认为为可以购买的瓷砖制作基类 TileOnSale 并制作实际类型的子类很可爱,我在下面的代码中提供了其中两个.

现在我的问题是如何访问未在父类 (TileOnSale) 中定义的子成员函数? Board 使用各种不同的图 block 进行初始化,因此我可以使用 getTile(int location) 函数从那里提取一个图 block 。但是,这会被解释为只是一个 Tile,而不是 TileOnSale 或 StreetTile。我知道没有办法以这种方式掌握 StreetTile 的 buildHouses 函数。

那么,是否有一种健壮的,甚至更好的,巧妙的方法来做到这一点?我可以制作一个模板或其他东西来保存可能是 StreetTiles 或 StationTiles 或其他 Tile 的 Tile 对象吗? 还是我应该重新设计类结构?

这是一个简单的代码。我试图只提供理解问题所需的内容。此外,最初 Tile 和 Board 在它们自己的头文件中。我决定没有必要显示具有自有 TileOnSale 对象 vector 但保留与 Board 完全相同的访问问题的 Player 类。

// Board.h
#include "Tile.h"
typedef vector<Tile> Tiles;

class Board
{
public:
    Board();
    ~Board();
    Tile            getTile(int location);
private:
    Tiles           tiles;
};

// Tile.h
class Tile
{
public:
    Tile();
    ~Tile();
protected:
    tileType    tile_type; // this is enum containing unique type
    string      description;
};

class TileOnSale : public Tile
{
public:
    TileOnSale();
    ~TileOnSale();

    virtual int getRent() const { return 0; };
};

class StreetTile : public TileOnSale 
{
public:
    StreetTile();
    ~StreetTile();
    int getRent() override;
    void buildHouses(int number);
private:
    int houses;
};

class StationTile : public TileOnSale
{
public:
    StationTile();
    ~StationTile();
    int getRent() override;
};

编辑:向代码添加了一个可能澄清的注释。

最佳答案

您可能想看一下 visitor pattern .

In essence, the visitor allows one to add new virtual functions to a family of classes without modifying the classes themselves; instead, one creates a visitor class that implements all of the appropriate specializations of the virtual function. The visitor takes the instance reference as input, and implements the goal through double dispatch.

双重分派(dispatch)意味着您实际上调用了一个虚函数两次:第一次调用主题,然后多态调用访问者。

在您的情况下,只有一种方法,即 build 房屋,但您可能希望稍后添加其他方法(例如在屏幕上绘制它们)。鉴于您当前的示例,您应该将此方法添加到 Tile 和 StreetTile:

virtual void accept(Visitor& v) { v.visit(*this); }

这是访问者基类的实现:

class Visitor {
public:
    virtual void accept(Tile& t) = 0;
    virtual void accept(StreetTile& t) = 0;
};

之后你可以实现一个Builder类:

class Builder: public Visitor {
private:
    int numberOfHouses;
public:
    Builder(int n): numberOfHouses(n) {}
    virtual void accept(Tile& t) {}
    virtual void accept(StreetTile& t) {
        t.buildHouses(numberOfHouses);
    }
};

在那之后,您所要做的就是构建这样一个构建器,并在您的瓦片 vector 中的每个瓦片上调用它:

Builder b(10);
for (Tile tile : tiles) {
    tile.accept(b);
}

关于c++ - 在父类中访问子类的功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20354164/

有关c++ - 在父类中访问子类的功能的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  3. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  4. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  5. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  6. Ruby——嵌套类和子类是一回事吗? - 2

    下面例子中的Nested和Child有什么区别?是否只是同一事物的不同语法?classParentclassNested...endendclassChild 最佳答案 不,它们是不同的。嵌套:Computer之外的“Processor”类只能作为Computer::Processor访问。嵌套为内部类(namespace)提供上下文。对于ruby​​解释器Computer和Computer::Processor只是两个独立的类。classComputerclassProcessor#Tocreateanobjectforthisc

  7. ruby-on-rails - Cucumber 是否只是 rspec 的包装器以帮助将测试组织成功能? - 2

    只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您

  8. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  9. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  10. ruby - 有没有办法从 ruby​​ case 语句中访问表达式? - 2

    我想从then子句中访问c​​ase语句表达式,即food="cheese"casefoodwhen"dip"then"carrotsticks"when"cheese"then"#{expr}crackers"else"mayo"end在这种情况下,expr是食物的当前值(value)。在这种情况下,我知道,我可以简单地访问变量food,但是在某些情况下,该值可能无法再访问(array.shift等)。除了将expr移出到局部变量然后访问它之外,是否有直接访问caseexpr值的方法?罗亚附注我知道这个具体示例很简单,只是一个示例场景。 最佳答案

随机推荐