2015-05-10 118 views
1

我目前在我的游戏和渲染引擎之间写了一个抽象层。不幸的是,我遇到了一个问题:我似乎无法将一个超类(抽象接口)转换为子类(具体引擎的实现)。这里是我的代码:无法将超类转换为子类

IInitationSettings.h

class IInitationSettings {}; 

OxygineInitiationSettings.h

#include "IInitiationSettings.h" 
#include "core/oxygine.h" 
class OxygineInitiationSettings : public IInitationSettings, public oxygine::core::init_desc { 
public: 
    OxygineInitiationSettings(const char* title, bool vsync, bool fullscreen, int width, int height); 
}; 

OxygineInitiationSettings.cpp

#include "OxygineInitiationSettings.h" 
OxygineInitiationSettings::OxygineInitiationSettings(const char* title, bool vsync, bool fullscreen, int width, int height) : oxygine::core::init_desc() { 
    this->title = title; 
    this->vsync = vsync; 
    this->fullscreen = fullscreen; 
    this->w = width; 
    this->h = height; 
} 

抽象init方法:

static void init(IInitiationSettings& initSettings); 
void GraphicsFactory::init(IInitiationSettings& initSettings){ 
#ifdef USE_OXYGINE_RENDERING 
    OxygineInitiationSettings settings = initSettings; //Does not work 
    oxygine::core::init_desc desc = initSettings; // Does not work 
    oxygine::core::init((oxygine::core::init_desc)((OxygineInitiationSettings)initSettings)); //Does not work 
#endif 
} 

如何将我的抽象接口转换为具体实现?我想添加一个newInitiationSettings-Method,它将返回一个IInitiationSettings对象,我将传递给init方法,以便拥有一个干净的代码。 (我希望我的游戏中,代码如下所示:

GraphicsFactory::init(GraphicsFactory::newInitiationSettings(args)); 

任何想法?

+2

不知道你在问什么。如何做[static_cast](http://en.cppreference.com/w/cpp/language/static_cast)或动态演员?如何避免需要施放? –

+0

究竟是行不通的?你能提供一些错误消息吗? –

+0

@AmiTavory Nah,我问为什么我不能将我的超类IInitationSettings投到我的子类OxygineInitationSettings – Fly

回答

2

这里的根本错误是尝试在抽象init方法中将对象本身转换为不同类型。向上(即朝向基类)投射结果为object slicing,因为它仅复制基类的数据。这通常很糟糕,但向下投射是不可能的。所以编译器不会让你。

你真正想要做的是在参考或指针级别工作。松散地说,引用是指针的语法糖,而指向对象的指针可以替代指向其基类之一的指针。这就是为什么你可以通过derived通过base&类型的参数。但是,当您尝试取回derived时,您必须要求derived&derived*。在你的情况,这看起来更像是其中之一:

static_cast<OxygineInitiationSettings&>(initSettings) // or 
dynamic_cast<OxygineInitiationSettings&>(initSettings) 

,或者,如果你需要一个指针,也许是这样的:

static_cast<OxygineInitiationSettings*>(&initSettings) // or 
dynamic_cast<OxygineInitiationSettings*>(&initSettings) 

如果你肯定知道initSettings将把一个OxygineInitiationSettings例如,您可以并应该使用static_cast而不是dynamic_cast。如果您不确定,您应该确定或使用dynamic_cast而不是static_cast。请注意,如果initSettings引用的实际对象实际上不是OxygineInitiationSettings,则动态引用强制将引发std::bad_cast异常,并且动态指针强制转换将返回空指针。

+0

感谢您的回答;但不幸的是,它不起作用。 IntelliJ强调static_cast并说“无效typeconversion” – Fly

+0

没关系,它的工作原理,我错误地键入“初始化”在标题类=) – Fly

+0

呃,我错了,不工作不幸...给我访问冲突... – Fly

1

Dynamic_cast可以从虚拟类执行,也就是具有虚拟方法的类。简单地增加假()方法这样的:

class IInitationSettings { 
    virtual void dummy() {} 
}; 

,并改变从隐性到动态转换:

void GraphicsFactory::init(IInitationSettings& initSettings) { 
    OxygineInitiationSettings settings = 
     dynamic_cast<OxygineInitiationSettings&>(initSettings); //Does indeed work 
} 

会解决问题。

+1

谢谢,它的工作原理!但为什么我需要添加一个虚拟方法来告诉编译器该类是抽象的?嗯,我更喜欢Java接口和抽象类更多... – Fly

+0

如果在类型是基类时删除(手动或使用任何智能指针包装器),则在基类上没有虚拟析构函数的语义不正确。所以,不,你不需要虚拟方法。改用虚拟析构函数;这可能是你真正想要的。 – Nate

相关问题