“(GameState *)new PlayingState()”有什么作用?

时间:2016-05-28 13:12:35

标签: c++ oop

该行

(GameState *) new PlayingState() 

对我来说没有多大意义。由于GameState*是指向类的指针,并且使用了new运算符,因此它显示PlayingState()是来自另一个类的“newed”对象。我的问题出现在本文末尾,但首先是各个类的定义:

class GameState
{
public:
    virtual void onStart(StateBasedGame &game) = 0;
};

class PlayingState : public GameState, public EventSubscriber<sf::Event>
{
public:
    PlayingState();
    void onStart(StateBasedGame &game);
};

我的问题:

1.它是否在课堂之间投射?您可以使用C ++转换类,例如在C中转换数据类型吗?我认为C ++更“正式”和“多余”?

2.你为什么这么做?这种转换有什么意义,作者可以达到什么目的?我猜这与构造函数有关。

3.对于new某事,你不应该采用这种格式吗?:

<class_type> <new_class_name> = new <class_type_name>

,如

GameState gameState = new PlayerState;

显然这不是唯一的方法吗?

3 个答案:

答案 0 :(得分:1)

如果没有进一步的背景,至少可以说这是奇怪的(我无法想象这实际上有意义的背景)。

首先,你是对的,在C ++样式代码中,你可以使用static_castdynamic_cast,根据情况,在类之间进行转换。

其次,由于PlayingState继承自GameState,指向PlayingState的指针(由new PlayingState()返回)可隐式转换为GameState*。根本不需要演员阵容。

在这种情况下,可以简单地使用:

GameState *gs = new PlayingState();

甚至更好,使用现代C ++:

auto gs = std::make_unique<PlayingState>()

(请参阅std::unique_ptrstd::make_uniqueauto

答案 1 :(得分:1)

(GameState *) new PlayingState() 

创建一个类PlayingState的新指针,然后将其强制转换为类GameState。

class PlayingState : public GameState, public EventSubscriber<sf::Event> {

是一个扩展GameState和另一个类的类。父类型的数据结构也得到了扩展。

class GameState

在Java / C#中可以被视为interface,因为只有纯虚方法(virtual <ret-type> <name>(<arguments>) = 0)。

虚拟方法存储在名为VMT(虚方法表)的东西中,并且对任何虚方法的函数调用都会通过索引调用VMT中的方法。

您不能像启动接口一样启动纯虚拟类。因此GameState gameState = new GameState无效。您还错过了GameState gameState的指针。

由于PlayingStateGameState的孩子,PlayingState只能在GameState投射到指针。

将您拥有的对象置于delete它。 delete gameState会这样做。

不要尝试free gameState,因为free不会调用析构函数例程。

修改

C ++还支持名为RTTI(运行时类型信息)的东西。在C ++中有const_castdynamic_castreinterpret_caststatic_cast

人们建议使用dynamic_cast进行父子投射的原因是因为可以进行基本的运行时类型检查。然后可以正确处理无法比较的类型,或者创建另一个指针 - 地狱。

dynamic_cast,请执行:

dynamic_cast<GameState *>(new PlayingState())

如果两种类型都不坚持任何关系,您可catch bad_cast

try {
    dynamic_cast<GameState *>(new PlayingState())
} catch (std::bad_cast &oops) {
    // nightmare
}

答案 2 :(得分:0)

PlayingStateGameState的子类。

所以演员阵容还可以。如果您需要返回基类的指针,那么如果您有用于操作基类的代码,则子类通常会在其基类中进行转换。

您还可以使用以下内容:

Parent *p;

if (...) {
    p = new Child1();
} else {
    p = new Child2();
}

//do stuff with p

但是,在将子指针转换为父指针时,不需要手动C样式转换。

我能想到的唯一一个例子是,如果你想调用一个存在于子节点和父节点中的函数,而不是virtual(在你的例子中,父节点中的所有函数都是虚拟的) ,虽然),然后你可以做:

((GameState*) new PlayingState()) -> doStuff(...)

但这是一种扭曲的方式,这也会起作用:

GameState *g = new PlayingState();
g->doStuff();

简而言之,如果没有更多关于演员的代码或背景,我只能认为这是不必要的,也是无害的冗余。

对于强制转换操作符,C ++中有几个。 dynamic_cast可用于将父项转换为子项(或甚至是同一孩子的父项之间)并安全地检查它是否可行,但这里没有用。