2011-05-25 55 views
15

確切的情況是: 我已經在系統API結構中定義了CGPointCGSize,我希望能夠寫出my_point = my_size。 我不能修改CGPoint結構體,只能寫外部運算符。我可以編寫二進制運算符(+,-,...),但operator=必須在結構中聲明。那麼還有其他解決方案嗎?是否可以在結構體外寫入自動投射運算符?

+1

什麼是點和大小之間的關係?大小怎麼可能是一個點?聽起來像不同的尺寸。 – 2011-05-25 07:43:04

回答

22

爲了表達a = b;編譯你需要,它利用b類型,或類型從b隱式轉換的元素a類型要麼有一個operator=

第一種情況被排除,因爲operator=必須是班級的成員,並且由於您無法修改GLPoint,因此您不能添加GLPoint& GLPoint::operator=(GLSize)

第二種情況存在相同類型的問題。從GLSizeGLPoint的隱式轉換可以作爲GLPoint(排除)中的隱式構造函數來實現,或者作爲中的成員operator GLPoint()來實現,這需要修改GLSize。轉換不能作爲自由功能添加。

替代方法使用非運算符語法,如添加免費函數assign(或copy):GLPoint& assign(GLPoint&, GLSize const &)

接下來的問題是你爲什麼要這麼做。如果GLPointGLSize的設計者不認爲大小應該可以分配給某個點,那麼您爲什麼覺得它們應該是可分配的?通常,將類型分開是個不錯的主意,因爲這將使編譯器能夠檢測到您在代碼中可能犯的錯誤。

如果允許GLSizeGLPoint隱式轉換,你可能會被錯誤類型是這樣的:distance(point1, size2),你的意思distance(point1, point2),而且因爲有一個轉換,編譯器會很高興地轉化和應用。然後你會看到奇怪的結果,你將花費不少好的調試時間,試圖確定邏輯錯誤的地方。

除非域名對每個運營商在這種情況下的含義有非常明確的定義,否則我將不惜一切代價避免運營商超載。將大家立刻讀懂你的代碼瞭解什麼GLPoint(1,2) + GLSize(5)代表毫無疑問或含糊不清?如果不是這種情況,如果人們會感到驚訝,甚至懷疑,則避免操作符重載和使用命名功能:move_up(GLPoint&, GLSize)(或任何點+尺寸意味着你)

+0

+1,關於轉換運算符陷阱的優秀註釋 – Nim 2011-05-25 07:46:51

+0

總體而言,通過對基礎語義的分析可以獲得極好的評論。 (顯然是基於名稱,但如果他的假設是錯誤的,名稱選擇非常差。) – 2011-05-25 08:01:04

+0

+1好帖子。尤其是最後一段。 – Nawaz 2011-05-25 08:03:44

2

當您將CGSizeCGPoint - 什麼發生?把它溶解到一些運營商那裏,然後你有它 - 例如

CGPoint& operator|=(CGPoint& cPoint, CGSize const& cSize) 
{ 
    // now set attributes of cPoint that you can extract from cSize 

    return cPoint; 
} 

這有什麼困難嗎?這裏是一個例子:http://www.ideone.com/FZN20

+1

對於簡單的情況,這是一個很好的解決方案,我想用CGSize在表達式中進行操作...... – brigadir 2011-05-25 08:39:23

+0

'我想在表達式中使用它'正確。例如在我的例子中,我想要做一些像'LONGLONG size = blah(); SetFilePointerEx(fh,size,NULL,FILE_BEGIN);'而不是必須做'LONGLONG size = blah(); LARGE_INTEGER tli = {0}; tli.QuadPart =大小; SetFilePointerEx(fh,tli,NULL,FILE_BEGIN);'如果我可以寫'LARGE_INTEGER operator =(LONGLONG ll){LARGE_INTEGER li = {0}; li.QuadPart = 11;返回li;}'(或者一個轉換操作符),那麼它會創建更簡單易用的代碼。 – Synetech 2013-07-17 17:23:41

+0

我更喜歡'operator <<' – kyb 2016-12-15 16:35:03

1

如果你可以派生或包裝CGPoint並在整個代碼中使用新類,那麼你可以提供你喜歡的任何操作符。新班級可以有一個轉換操作員到CGPoint,以促進與現有功能的交互。

+1

這很容易出問題而不是幫助。繼承是第二大耦合關係,應該避免,除非它是有道理的,在這種情況下,我不認爲它是確實存在的。考慮現有的代碼仍然會返回非派生類型,然後您將混合可以分配不能的點的點。更糟糕的是,目前的系統可能會希望'GLPoint'的容器,如果它是按值的,那麼它不會接受新的類型,如果它是通過指針,並且它試圖在內部「刪除」,那麼你是在未定義的行爲土地... – 2011-05-25 07:55:21

+0

@大衛:他們當然是考慮,應該指導選擇派生與包裝/組成,並可以使我列出的技術不適合特定問題。平衡取決於需要「真正的」GLPoint的函數與可能受益於此賦值符號的便利性的應用程序內部代碼量的多少交互點。直到OP來評估他們的情況。 – 2011-05-25 09:11:30

0

其他答案接縫錯過顯而易見的解決方案:添加一個函數將CGPoint轉換爲CGSize。關當然,這不是正是你想要的(size = point),但因爲你不能修改兩類要麼,這是唯一的方法:

CGSize ToSize(const CGPoint &pt) 
{ 
    CGSize res = ... 
    // do the conversion 
    return res; 
} 
+0

這並不像實際使用操作符那麼理想,但它應該在大多數情況下工作。 (實際上,由於常規函數調用可能導致操作員無法做到這一點,所以更讓人困惑) – Synetech 2013-07-17 17:25:46

+0

@Synetech我的經驗是,轉換操作員可能會引入混淆,並且最好避免 – 2013-07-17 20:21:11

+0

在很多情況下,但如果創建該類的原始開發人員設計得不夠好,那麼使用轉換操作符可以使其更易於使用,就像使用LARGE_INTEGER一樣。 – Synetech 2013-07-18 18:43:54

相關問題