该行
(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;
显然这不是唯一的方法吗?
答案 0 :(得分:1)
如果没有进一步的背景,至少可以说这是奇怪的(我无法想象这实际上有意义的背景)。
首先,你是对的,在C ++样式代码中,你可以使用static_cast
或dynamic_cast
,根据情况,在类之间进行转换。
其次,由于PlayingState
继承自GameState
,指向PlayingState
的指针(由new PlayingState()
返回)可隐式转换为GameState*
。根本不需要演员阵容。
在这种情况下,可以简单地使用:
GameState *gs = new PlayingState();
甚至更好,使用现代C ++:
auto gs = std::make_unique<PlayingState>()
答案 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
的指针。
由于PlayingState
是GameState
的孩子,PlayingState
只能在GameState
投射到指针。
将您拥有的对象置于delete
它。 delete gameState
会这样做。
不要尝试free
gameState
,因为free
不会调用析构函数例程。
修改强>:
C ++还支持名为RTTI
(运行时类型信息)的东西。在C ++中有const_cast
,dynamic_cast
,reinterpret_cast
和static_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)
PlayingState
是GameState
的子类。
所以演员阵容还可以。如果您需要返回基类的指针,那么如果您有用于操作基类的代码,则子类通常会在其基类中进行转换。
您还可以使用以下内容:
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
可用于将父项转换为子项(或甚至是同一孩子的父项之间)并安全地检查它是否可行,但这里没有用。