2010-01-27 40 views
2

我寫了一個自定義SDL GUI工具包(源位於http://sourceforge.net/projects/lkgui/files/),並且遇到了繼承對象的問題。對象在主程序中崩潰,但不在移動到單元時

當對象位於主程序中時,構造函數不會被調用,因此程序沒有正確初始化該對象,並且在某些命令後崩潰(具體來說,TStartGameButton繼承自GUI_Canvas,繼承自GUI_Element,在GUI_Element中定義的程序使用EAccessViolation崩潰)。當物體放置在一個單元內時,這個問題就消失了。

我明白我可以將它留在單元中,但它會導致一些可能希望避免的醜陋代碼。

有沒有人有任何想法,爲什麼這可能會發生,我怎麼可能避免它?

+0

整個存檔不會在tstartgamebutton上grep。 – 2010-01-27 14:13:33

回答

3

自從Delphi 2發佈以來,舊式的Delphi對象已經被打破,可能更早。當他們具有編譯器管理類型的字段時,他們不會很好地繼承,例如string或動態數組。 2004年有a discussion about itcomp.lang.pascal.delphi.misc。這裏是代碼重現它:

type 
    TBase = object 
    public 
    s: string; 
    end; 

    TDerived = object(TBase) 
    end; 

procedure test; 
var 
    obj: TDerived; //okay for TBase! 
begin 
    assert(obj.s = '', 'uninitialized dynamic variable'); 
end; 

而事實上,這只是爲確定由TBase事故由於功能的開場白代碼是如何發生的產生。在該函數中添加額外的代碼可以使其崩潰。

事實上,正如你所看到的那樣 - 老式對象不能正確初始化。他們的字符串字段沒有開始持有空字符串;相反,他們擁有垃圾,所以甚至無法使用FillChar之類的東西來自行初始化它們。

這似乎是由於變量爲本地變量。單元範圍(「全局」)變量似乎工作正常。在單元範圍內聲明但僅用於單元的初始化部分或程序範圍並僅用於DPR文件的主要開始結束塊的變量被編譯器視爲局部變量,因此它們未被設置爲全部像他們的全球同行零位零。當你將你的變量聲明移動到一個單元,但繼續在你的DPR文件中使用它時,它會被提升到「全局」狀態。

您的TGUI_Element類型有一個string成員0123',它看起來就是您在類型層次結構中唯一的字符串字段。拿出來,或改爲ShortString,我敢打賭你的崩潰至少暫時消失。

+0

嗯,看起來FPC在這裏是bugcompatible,在這裏也看不到obj的初始化 – 2010-01-27 15:25:35

+0

是的 - 將它改爲ShortString可以解決問題。謝謝。 具有諷刺意味的是幫助我調試的功能是它崩潰的原因... – lochok 2010-01-27 22:43:48

0

爲什麼要給所有對象個別命名的構造函數而不是使它們變爲虛擬的?

type tx = object 
       constructor init; virtual; 
       end; 
     txx = object(tx) 
        constructor init; virtual; // like override in Delphi classes. 
        end; 

如果你需要一個視覺層次看,看看免費的視力,它表明幾乎每一個方面的TP對象模型的

哎呀 apparantly虛擬構造函數是不可能的TP模型

+0

主要是因爲我不知道我可以:S – lochok 2010-01-27 22:29:41

+0

這應該起作用嗎?我改變了一切虛擬構造函數,並得到如下:錯誤:虛擬構造函數只支持類對象模型 – lochok 2010-01-28 03:20:33

+0

不,Lochok,它不應該工作。編譯器是正確的。虛擬構造函數只有在可以通過引用引用* type *時纔有用,但只有類可以使用,而不能使用舊式對象。 – 2010-01-28 14:49:40

相關問題