2010-09-03 58 views
15

我正在瀏覽OpenDE的源代碼,並且在類中遇到了數組索引操作符'[]'的一些奇怪的語法用法。這裏有一個簡單的例子來說明語法:這個C++語法是什麼意思,它爲什麼起作用?

#include <iostream> 

class Point 
{ 
public: 
    Point() : x(2.8), y(4.2), z(9.5) {} 

    operator const float *() const 
    { 
     return &x; 
    } 

private: 
    float x, y, z; 
}; 

int main() 
{ 
    Point p; 
    std::cout << "x: " << p[0] << '\n' 
       << "y: " << p[1] << '\n' 
       << "z: " << p[2]; 
} 

輸出:

x: 2.8 
y: 4.2 
z: 9.5 

這是怎麼回事?爲什麼這個語法工作? Point類不包含重載operator [],此處此代碼嘗試執行自動轉換以在某處浮動。

我從來沒有見過這種用法 - 它絕對看起來很不尋常和令人驚訝的至少可以說。

由於

+4

請注意,要查明它是使用'operator []'還是使用指針轉換函數,您可以做這個奇怪的測試:如果'0 [p]'工作,它使用指針轉換。如果它不起作用,但如果'p [0]'起作用,則它使用'operator []'。 – 2010-09-05 12:23:18

回答

17

p被隱式轉換成const float* const,它指向x。所以*px,*(p+1)y,依此類推。 這是一個非常奇怪的想法(並且令人困惑!)當然這樣做。通常最好將x,y和z存儲在一個數組中,並且如果他們真的想這樣做,就有一個獲得整個數組的函數。

+19

更不用說這是完全不安全的,因爲'x','y'和'z'的內存位置沒有明確定義。 – 2010-09-03 02:49:07

+0

ahhh okie謝謝。這是一些聰明的代碼...也許太聰明: – greatwolf 2010-09-03 02:50:14

+2

@ D.Shawley:一個很好的觀點。雖然「合理的」編譯器可能會這樣做,但我不相信這種佈局是標準的。 – rlbond 2010-09-03 02:55:25

1

這只是將您的成員數據視爲數組的一種方式。你也可以用結構來做到這一點。當你想要可讀性,但希望能夠遍歷簡單的數據結構時,這很有用。一個例子使用會宣佈一個矩陣是這樣的:

typedef struct { 
    CGFloat m11,m12,m13,m14; 
    CGFloat m21,m22,m23,m24; 
    CGFloat m31,m32,m33,m34; 
    CGFloat m41,m42,m43,m44; 
} CATransform3D; 

您可以方便地通過名稱引用的每個細胞,但你也可以通過圍繞一個指針M11無處不在(和C會看到你的結構爲一個數組, m11是第一個元素),並遍歷所有元素。

8

這裏的想法是通過下標或名稱來訪問Point的成員。如果你想這樣做,但是,你會更好過載operator[]是這樣的:

struct Point { 
    float x, y, z; 

    float &operator[](size_t subscript) { 
     switch(subscript) { 
      case 0: return x; 
      case 1: return y; 
      case 2: return z; 
      default: throw std::range_error("bad subscript"); 
     } 
    } 
}; 

這樣,如果編譯器插入彩車之間的填充,它仍然會工作 - 和任何人誰可以閱讀C++應該能夠理解它,沒有任何問題。

+1

好點。這也是我的想法。我知道當我仔細閱讀源代碼時,代碼的作用並不明顯。我認爲這絕對屬於「爲自己的利益而過於聰明的代碼」。 :P – greatwolf 2010-09-03 03:30:57

+0

爲'正確'代碼+1 - 安全,處理錯誤,可讀等。 – JBRWilkinson 2010-09-03 08:16:17