我是Delphi中的新手。對於我公司所需的項目,我需要將我們現有C++類的一些代碼翻譯成Delphi。其中一些類別是模板,例如:在Delphi中使用泛型類型的算術操作
template <class T>
struct APoint
{
T m_X;
T m_Y;
virtual void Add(T value);
};
template <class T>
void APoint<T>::Add(T value)
{
m_X += value;
m_Y += value;
}
我使用它,例如用此代碼
APoint<float> pt;
pt.m_X = 2.0f;
pt.m_Y = 4.0f;
pt.Add(5.0f);
這個效果很好。
現在我需要編寫Delphi的等效代碼。我試圖編寫一個基於上面的C++代碼的Delphi通用類:
APoint<T> = record
m_X: T;
m_Y: T;
procedure Add(value: T);
end;
procedure APoint<T>.Add(value: T);
begin
m_X := m_X + value;
m_Y := m_Y + value;
end;
但是,此代碼無法編譯。我得到這個錯誤:
E2015 Operator not applicable to this operand type
AFAIK這個代碼應該工作,我不明白它有什麼問題。所以有人可以向我解釋:
爲什麼這樣的代碼不能在Delphi中編譯?
什麼是在Delphi中創建模板類的最正確(最簡單)的方法,該模板類提供了一個
Add()
函數,儘可能接近C++代碼和上面的用法?
修改是在2016年10月17日
感謝所有的答覆。所以,如果我理解正確,就沒有辦法創建類似於C++的樣式模板,因爲Delphi強加了幾個在C++中不存在的約束。
基於此,我搜索了一個解決方法以達到我想要的目標。我發現以下解決方案:
IPoint<T> = interface
procedure Add(value: T);
end;
APoint<T> = class(TInterfacedObject, IPoint<T>)
m_X: T;
m_Y: T;
procedure Add(value: T); virtual; abstract;
end;
APointF = class(APoint<Single>)
destructor Destroy; override;
procedure Add(value: Single); reintroduce;
end;
destructor APointF.Destroy;
begin
inherited Destroy;
end;
procedure APointF.Add(value: Single);
begin
m_X := m_X + value;
m_Y := m_Y + value;
end;
我使用它用此代碼
procedure AddPoint;
var
pt: IPoint<Single>;
begin
pt := APointF.Create;
APointF(pt).m_X := 2.0;
APointF(pt).m_Y := 4.0;
APointF(pt).Add(5.0);
end;
這個效果很好。不過,我覺得風格有點沉重,例如使用APointF(pt)的必要性。所以,關於上面的代碼,我的問題是:
- 這個解決方案是一個很好的解決方案嗎? (也就是說,最好爲每個我想支持的類型寫每個記錄的一個版本,例如像APointF,APointI,APointD,...)
- 有沒有簡化此代碼的方法,例如,沒有APointF(pt)轉換直接調用pt.m_X的解決方案? (注意我在這裏省略了屬性的實現,即使我認爲它們比直接訪問變量更優雅)
- 這個解決方案的性能如何? (也就是說,這個解決方案比直接m_X:= m_X +增加的速度慢得多?)
最後,我看到了在Delphi代碼,它可以實現2種泛型類型的相等比較這樣另一種解決方案:
function APoint<T>.IsEqual(const other: APoint<T>): Boolean;
var
comparer: IEqualityComparer<T>;
begin
Result := (comparer.Equals(m_X, other.m_X) and comparer.Equals(m_Y, other.m_Y));
end;
我試圖讀取幕後的代碼但是我發現它非常複雜。所以,我的問題是:
- 是否這樣的解決方案比上面提出的更好?
- 數學運算中是否有類似的隨時可用的解決方案?
- 此類解決方案的性能是否可以接受?
在此先感謝您的答覆
問候
[泛型約束](http://docwiki.embarcadero.com/RADStudio/en/Constraints_in_Generics)不能定義序也不浮動。這是你在這裏看到的,因爲每個'T'沒有算術運算符。 –
這裏用泛型和算術運算符完成一些測試:https://delphihaven.wordpress.com/2011/03/18/generic-arithmetic/。 –
*「Delphi中的泛型不同於C++中的模板或C#中的泛型類型。最值得注意的是,類型參數不能限制爲特定簡單類型,例如Integer,Double,String等。 http://docwiki.embarcadero.com/RADStudio/en/Overloads_and_Type_Compatibility_in_Generics) –