2016-05-17 51 views
2

--University homework--返回泛型函數對象的引用(與指針或非指針屬性)

我已經與通用功能看起來像這樣的工作:

template<class T1, class T2, int max> 
class Collection{ 
    T1* _elements1[max]; 
    T2* _elements2[max]; 
    int _count; 
public: 
    // ctor 

    bool AddElement(const T1& e1, const T2& e2) 
    { 
     for (int i = 0; i < _count; i++) 
      if (_elements1[i] == e1 && _elements2[i] == e2) 
       return false; 

     _elements1[_count] = e1; 
     _elements2[_count] = e2; 

     _count++; 

     return true; 
    } 

    int GetMax()const { return max;} 
    T1& GetElement1(int index)const { return *_elements1[index]; } 
    T2& GetElement2(int index)const { return *_elements2[index]; } 
} 

main()

Collection<int, double, 6> collection; 

for (int i = 0; i < 6; i++) 
    collection.AddElement(i, i + 0.4); 

cout << collection << endl; 

我也用constoperator<<這個類,一切的偉大工程,與0123沒有編譯器的投訴。

但是,今天我嘗試了這個班的稍微不同的版本,我們應該練習,因爲它會以某種形式在考試中。

template<class T1, class T2, int max> 
class Collection{ 
    T1 _elements1[max]; 
    T2 _elements2[max]; 
    int _count; 
public: 
    // ctor 

    int GetMax()const { return max;} 
    T1& GetElement1(int index)const { return _elements1[index]; } 
    T2& GetElement2(int index)const { return _elements2[index]; } 
} 

的此不同的是,T1T2不是的pointers數組,但純對象數組,並在底部,當return ING,有沒有必要取消引用。雖然我做google一下,發現如果我把另一個const在這些功能中的前像這樣

error C2440: 'return' : cannot convert from 'const int' to 'int &' 

const T1& GetElement1(int index)const { return _elements1[index]; } 
const T2& GetElement2(int index)const { return _elements2[index]; } 

然而,在後者的例子中,我得到這個錯誤

錯誤消失。

當然,這解決了我的問題,但我寧願瞭解爲什麼會發生這種情況以及發生了什麼。如果有一個簡單的方法可以解釋我提供的兩個示例之間的差異,那麼將不勝感激。

+0

是什麼例子中的'T1'和'T2'無法編譯? – NathanOliver

+0

在這個階段,我分別用'int'和'double'測試了一個簡單的for循環,調用集合函數AddElement(const T1&e1,const T2&e2)。請注意,在另一個示例(其中T1和T2是指針數組)中應用了相同的測試,並且它不會失敗。 – developer10

+0

所以你同時調用'GetElement1'和'GetElement2',但只有'GetElement1'出錯? – NathanOliver

回答

1

在第一Collection版本,_elements1[index]int *const&類型。這const是因爲您訪問const方法(實際上thisconst在這種情況下)_elements1方法,這也意味着您不允許修改_elements1[index]。當你取消_elements1[index]你會得到int&,這是_elements1[index]指向的東西。所以你可以從GetElement1返回它,它返回T1&

現在到你的第二個集合類。 GetElement1方法中的_elements1[index]方法類型爲const int&,因爲在const方法中訪問_elements1之前添加了const。現在你錯誤的原因是因爲你不能將const int&隱含地轉換爲int&

如果你想了解什麼類型_elements1[index]你可以在下面招用不同的地方:

template<typename T> 
struct TD; 

// ... 

T1& GetElement1(int index)const { 
    TD<decltype(_elements1[index])> tt;   
    return _elements1[index]; 
    } 

將輸出誤差確切類型的裏面是什麼上面decltype:

error: implicit instantiation of undefined template 'TD<const int &>' 
                 ^^^^^^^^^^^ - type of _elements1[index] 
1
T1& GetElement1(int index)const { return _elements1[index]; } 

對於成員函數,編譯器會將類本身(this)作爲第一個參數傳遞給函數。由於成員函數聲明之後的const修飾,GetElement1的第一個參數是常量集合,而不是收集

編輯:

#include "iostream" 
#include "string" 

template<class T1, class T2, int max> 
class Collection{ 
    T1* _elements1[max]; 
    T2* _elements2[max]; 
    int _count; 
public: 
    Collection() { 
     for (size_t i = 0; i < max; ++i) { 
      _elements1[i] = new T1{}; 
      _elements2[i] = new T2{}; 
     } 
    } 
    int GetMax()const { return max;} 
    const T1& GetElement1(int index) const { 
     // _elements1[0] = new T1{}; Error, the pointer is constant 
     _elements1[0]->resize(5); // Ok, the pointed object isn't constant 
     return *_elements1[index]; 
    } 
    const T2& GetElement2(int index) const { return *_elements2[index]; } 
}; 

int main() { 
    Collection<std::string, std::string, 5> c; 
    const std::string& rs = c.GetElement1(1); 
    return 0; 
} 
+0

好吧,爲什麼當'T1'是一個指針數組並且我將其返回(取消引用)時,同樣的錯誤不會顯示? – developer10

+1

@ developer10 - 指針指向課堂以外的東西。指針可能是恆定的,但不是它們指向的東西。 –

+0

@BoPersson所以即使我返回值本身(例如指針,請注意「*」):'T1&GetElement1(int index)const {return * _elements1 [index]; },它在這種情況下有所不同? – developer10