2011-02-24 80 views
1

對於標題,我很抱歉。我似乎有一個問題。我只是一個初學者,我很抱歉,如果之前問過這個問題,我無法找到一個直接的答案。 (當我搜索類,指針和孩子,我得到了關於傳遞父或子指針的結果......我不想傳遞(this)子或父指針,我只想傳遞一個指針,我初始化了一個子類。 。給父母)。C++在子類的父類中設置指針變量,並在父類中使用它

class App 
{ 
public: 
    virtual void init(void)   { window = &BasicWindow(); } 
    virtual void createWindow(void) { window->create(); } 

protected: 
    Window *window; 
}; 

class Game : public App 
{ 
public: 
    virtual void init(void)   { window = &OpenGLWindow(); } 
}; 

int main() 
{ 
    App *game = &Game(); 
    game->init(); 
    game->createWindow(); 
    return 0; 
} 

這是合法的:什麼,我想在這裏做的是更好地解釋代碼? 我有一個從BasicWindow和OpenGLWindow派生的抽象Window類。 但是,當我創建窗口時,我在App::createWindow()函數中得到了Access violation reading location錯誤中斷window->create()

感謝

回答

4

我猜這是因爲你指向一個臨時的:

window = &BasicWindow() 

一旦函數退出,window點「廢話」和壞的事情會發生。

想必,你想要做的是創建窗口的新實例 - 即

window = new BasicWindow(); 

不要忘了清理!

+0

Omg,我現在感覺很愚蠢。謝啦!我以爲我不需要製作'新'類的實例,因爲我只需要一個窗口。但似乎我誤解了'在範圍內使用它'的部分。 – Nique 2011-02-24 09:39:39

+3

@Nique,不要,我敢肯定,我們都在學習C++的漫長而艱難的道路上犯了類似的錯誤...... :) – Nim 2011-02-24 09:43:25

2

window是類App的未初始化指針。因爲,沒有你要撥打init的方法。所以,當調用基類createWindow()時,window->create()結果錯誤。

編輯1

至於現在,每一件事情在語法上是正確的,但呆在一起肯定你想達到的目標。不要創建臨時/無名稱的對象並分配它們。取而代之的是用運營商newwindow = &BasicWindow();window = &OpenGLWindow();中構建它們。由於班級管理資源,您應遵循原則Rule of Three。也知道聲明 -

App *game = new Game(); 

靜態類型的操作數(應用*)從動態類型(遊戲*)不同。在這種情況下,靜態類型充當基類,它的析構函數必須是虛擬的,否則行爲是未定義的。所以,應用程序類的析構函數必須是虛構的

+0

+1哎呀,我錯過了! :D,我想我會留下我的答案,因爲我認爲它仍然有效! – Nim 2011-02-24 09:34:36

+0

對不起,我轉載的情況。實際上,我在App-> start()上調用init(); – Nique 2011-02-24 09:35:22

+0

@編輯1,我不再需要在主要功能(或其他任何地方)的遊戲了。我真的需要創建對象的新實例嗎?我的檔案:以及在任何操作系統中創建窗口的面向對象的方式。我不想要這些醜陋的消息處理器在主內 – Nique 2011-02-24 09:51:10

1

該錯誤可能與您正在使用指向臨時對象的事實有關。

virtual void init(void)   { window = &BasicWindow(); } 

該指針在「;」後變爲無效。使用「新」而不是「&」。 如果你想使用窗口指針,你需要調用game-> init()(甚至更好地放在構造函數中,那就是它們的用途)。

除此之外,更改基類的受保護成員是完全合法的。

2

我打算踢你從Objective-C來的? ;)

我認爲你的問題都來自不瞭解如何創建C++對象。

首先:window = &BasicWindow();是不是你應該如何創建一個新的對象。您需要使用window = new BasicWindow;這會導致在內存中分配BasicWindow的空間,並且將調用BasicWindow的默認構造函數。

你的main()方法有類似的錯誤,但是在這種情況下,你不需要使用new來分配它,你可以聲明一個實例並將它創建在堆棧上。然後

你的主要方法是這樣的:

int main() 
{ 
    Game game; 
    game.createWindow(); 
    return 0; 
} 

剩下的問題是,你的init方法不會被調用。在C++中,構造函數會自動調用,並且與該類名稱相同。對於遊戲類的例子默認構造函數是:

Game() { window = new OpenGLWindow(); } 

你需要知道的另一件事是,不像客觀C,構造的整個層次結構時,會自動創建一個對象調用。也就是說,當你創建一個Game的實例時,它的構造函數以及每個基類的構造函數都會被調用。實際上,基類構造函數被稱爲FIRST。所以在你的情況下,如果你只是將init方法改爲構造函數,你將分配兩個窗口(每種類型之一)並泄漏BasicWindow。這不是很酷。

你應該把它們留在名爲init的位置,並且確保在創建後立即調用它。

總之,試試這個:

class App 
{ 
public: 
    virtual void init(void)   { window = new BasicWindow; } 
    virtual void createWindow(void) { window->create(); } 
protected: 
    Window *window; 
}; 

class Game : public App 
{ 
public: 
    virtual void init(void)   { window = new OpenGLWindow; } 
}; 

int main() 
{ 
    Game game; 
    game.init(); 
    game.createWindow(); 
    return 0; 
} 

(不要忘了清理new'd對象!)

編輯(例如添加完成清理):

class App 
{ 
public: 
    App() : window(NULL)  {} 
    virtual ~App()    { delete window; } 
    virtual void init()   { window = new BasicWindow; } 
    virtual void createWindow() { window->create(); } 
protected: 
    Window *window; 
}; 

class Game : public App 
{ 
public: 
    virtual void init()   { window = new OpenGLWindow; } 
}; 

int main() 
{ 
    Game game; 
    game.init(); 
    game.createWindow(); 
    return 0; 
} 
+0

+1好的答案。如果你在App中添加了一個虛擬析構函數,它會更好 - 也許是一個檢查窗口是否爲零指針,然後刪除它,如果不是? – Tom 2011-02-24 10:00:25

+0

我不是來自目標C ..我來自面向對象的PHP腳本。我知道關於構造函數和析構函數的故事。但是當我試圖改變窗口的父構造函數的實例時,它讓我困惑。所以這正是我創建init()方法的原因。感謝您指出了這一點!,無法解釋更好。感謝您的有用答案。 (我乾的更乾淨的主)game.run()..和運行照顧做init()和創建窗口。 – Nique 2011-02-24 10:01:23

+0

@Tom如果我們按照你說的添加了析構函數,我們還需要確保構造函數設置window = NULL,否則它將是隨機存儲器,並且在未初始化時很可能不爲零。我不想走那麼遠,冒險讓它變得混亂:) – 2011-02-24 10:05:08