2013-06-05 70 views
1

我在C++中有一個數據結構類,有一個對象的訪問器(可能很大),我有const和非const方法使用這個訪問器,所以我需要超載它。我正在尋找批評的下面的代碼 - 也許有一種方法來完成同樣的事情,更清潔?重載的const和非const類方法返回C++中的引用

我瞭解它的方式有兩種方法可以在不重複訪問器中的代碼的情況下使用方法get()。我不確定這兩種方法是否存在嚴重問題,並且我想在此處提供一些指導

我喜歡的方法A,因爲:

  • 只有一個const_cast會
  • GET方法(的常量版)返回一個副本
  • 非const方法獲取非const引用直接

我不喜歡方法的原因是:

  • 非const get()方法是常量僅通過合同,(不是由編譯器檢查)
  • 更難獲得一個const參考,雖然不是不可能

我喜歡方法B,因爲:

  • const的GET方法的常量性()由編譯器檢查返回的對象的
  • 副本由用戶控制

我不喜歡方法B,因爲:

  • 需要兩個const_casts這是難以閱讀

這裏是這兩種情況的(最小)的示例代碼。

/** 
* summary: 
* Two classes with an overloaded method which is 
* guaranteed (by contract) not to change any 
* internal part of the class. However, there is a 
* version of this method that will return a non-const 
* reference to an internal object, allowing the user 
* to modify it. Don't worry about why I would ever 
* want to do this, though if you want a real-world 
* example, think about std::vector<>::front() 
* 
* The difference between A and B can be summarized 
* as follows. In both cases, the second method merely 
* calls the first, wrapped with the needed 
* const_cast's 
* 
* struct A { 
*  int& get(); 
*  int get() const; 
* }; 
* 
* struct B { 
*  const int& get() const; 
*   int& get(); 
* }; 
* 
**/ 

struct A 
{ 
    int _val; 

    A() : _val(7) {}; 

    // non-const reference returned here 
    // by a non-const method 
    int& get() 
    { 
     // maybe lots of calculations that you do not 
     // wish to be duplicated in the const version 
     // of this method... 
     return _val; 
    } 

    // const version of get() this time returning 
    // a copy of the object returned 
    int get() const 
    { 
     // CONST-CAST!!?? SURE. 
     return const_cast<A*>(this)->get(); 
    } 

    // example of const method calling the 
    // overloaded get() method 
    int deep_get() const 
    { 
     // gets a copy and makes 
     // a copy when returned 
     // probably optimized away by compiler 
     return this->get(); 
    } 
}; 

struct B 
{ 
    int _val; 

    B() : _val(7) {}; 

    // const reference returned here 
    // by a const method 
    const int& get() const 
    { 
     // maybe lots of calculations that you do not 
     // wish to be duplicated in the non-const 
     // version of this method... 
     return _val; 
    } 

    // non-const version of get() this time returning 
    // a copy of the object returned 
    int& get() 
    { 
     // CONST-CAST!? TWO OF THEM!!?? WHY NOT... 
     return const_cast<int&>(const_cast<const B*>(this)->get()); 
    } 

    // example of const method calling the 
    // overloaded get() method 
    int deep_get() const 
    { 
     // gets reference and makes 
     // a copy when returned 
     return this->get(); 
    } 
}; 


int main() 
{ 
    A a; 
    a.get() = 8; // call non-const method 
    a.deep_get(); // indirectly call const method 

    B b; 
    b.get() = 8; // call non-const method 
    b.deep_get(); // indirectly call const method 
} 
+1

如果你的代碼有沒有問題(你是知道的),那麼這可能屬於對http://codereview.stackexchange.com/ –

+0

啊,沒不知道該網站存在,謝謝!我只是在codereview上創建了同樣的問題。 http://codereview.stackexchange.com/questions/27064/overloaded-const-and-non-const-class-methods-returning-references-in-c – Johann

+0

投票結束在這裏,因爲它已交叉發佈到代碼審查。 http://codereview.stackexchange.com/questions/27064/overloaded-const-and-non-const-class-methods-returning-references-in-c/27161#27161 –

回答

2

成員函數的常量性應當基於問題來決定:是在上下文中用於修改該對象的成員函數?(成員可以直接修改對象,或者返回一個引用/指向內部數據的指針,以便外部調用者可以修改該對象)。如果是,請將其設爲非const,否則將其設爲const。

編譯器將正確選擇不同於常量的重載。但是,返回類型不用於重載分辨率。此外,按價值/按參考值計算的退貨應僅根據預期成本和您將返回的預期所有權來決定。幸運的是,C++ 11通過提供move semantics使生活更輕鬆。這意味着您可以愉快地返回大數據結構。如果被引用的對象將超出外部調用者,則只能通過引用返回。

在我看來,你的int& get()應改名void set(int)而且你可以在你的int get() const分成計算助手和適當get()

class C 
{ 
    int val_; 
public: 
    void modify() { /* some expensive computation on val_ */ } 
    int get() const { return val_; } 
    void set(int v) { val_ = v_; } 
}; 

另外,如果你想保持到get()功能,你可以做

class D 
{ 
int val_; 
public: 
    void modify() { /* some expensive computation on val_ */ } 
    int get() const { modify(); return val_; } 
    int& get()  { modify(); return val_; } // no const-cast needed 
}; 
+0

也許我的代碼太少了。想象一下,get()實際上是get(string),並且有很多(可能是遞歸的)計算與字符串一起完成以確定返回哪個對象。我正在尋找返回(公共)成員對象的引用,但也能夠從const方法調用相同(或重載)的方法。 – Johann

+1

@Johann同樣的事情:寫一個執行計算的助手函數,並寫2'get()'函數來返回每個調用內部計算助手的對象狀態。 – TemplateRex

相關問題