2015-05-10 276 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

相關問題