2010-02-14 70 views
3

我有3個類。在它最簡單的形式,它看起來像,使用常量和非常量函數 - C++

class tree 
{ 
public: 
    tree_node* find_node(const std::string& text) { 
     return factory.find(text); 
    } 
private: 
    tree_node_factory factory; 
} 

class tree_node 
{ 
public: 
    tree_node(const std::string& text) : text_(text) {} 

    const std::string& text() const { 
     return text_; 
    } 

    void set_parent(const tree_node* new_parent); 

private: 
    std::string text_; 
} 

class tree_node_factory 
{ 
public: 
    tree_node* find(const std::string& text); 
private: 
    std::vector<tree_node*> allocated_nodes; 
} 

我不想讓的tree用戶修改通過像find_node方法返回的tree_node。所以我改變了,find_nodetree_node_factory::find

const tree_node* find_node(const std::string& text) const { 
    return factory.find(text); 
} 

const tree_node* find(const std::string& text) const; 

問題是tree內部應該可以修改節點,像set_parent方法的工作。但由於工廠僅返回const節點,我最終在工廠中增加了另一個過載(非常量版本)find

tree_node* find(const std::string& text); 

我想知道這是處理這類問題的正確方法嗎?我發現代碼在const和非const版本中得到了重複。

任何想法..?

+1

這是正常的;看看大多數STL類,你會看到它們提供了const和非const的版本。我認爲Sutter談論了一種使用(格式良好)'const_cast'和'static_cast'的方式來刪除代碼重複(通過調用其他版本);我懷疑有人會發布它。但是,這是正常的。 – GManNickG 2010-02-14 06:52:03

+0

很酷。謝謝GMAN。 – 2010-02-14 06:56:19

+0

Duplicate - http://stackoverflow.com/questions/123758/how-do-i-remove-code-duplication-between-similar-const-and-non-const-member-funct – Manuel 2010-02-14 07:54:28

回答

3

不幸的是,C++沒有工具(除了宏)消除了函數過載中的源代碼重複,這些函數過載看起來大致相同但常量不同。但是,您可以使用其他功能和const_cast實現其中一項功能。

7

Scott Meyers的書中的第3項Effective C++演示了一種刪除此代碼重複的方法。基本上,在你的非const函數中,你將const添加到this,調用const版本,然後把const扔掉。這是安全的;儘管寫入const變量會導致未定義的行爲,因爲this最初是非const的,這沒關係。

實施例:

const std::string& operator[](size_t index) const 
{ 
    // some other code 

    // since `this` isn't really const, this is modifiable 
    return mData[index]; 
} 

std::string& operator[](size_t index) 
{ 
    return const_cast<std::string&> // (3) take const off result 
      (static_cast<const my_type&> // (1) add const 
      (*this)[index]); // (2) use const version 

} 

通常,它都將是在一行上。你也可以爲它製作一個實用程序。

注意一個警告:如果const版本返回一個「真正的」const對象,這種方法明顯導致未定義的行爲。返回值的常量必須通過this所提及的對象的常量來反映。這是破碼:

const std::string& operator[](size_t index) const 
{ 
    static const std::string constString = "Don't modify me."; 

    if (index == 0) 
    { 
     // even though `this` isn't really const, this is NOT modifiable 
     return constString; 
    } 

    return mData[index - 1]; 
} 

std::string& operator[](size_t index) 
{ 
    return const_cast<std::string&> // (3) !!! take const off result !!! 
      (static_cast<const my_type&> // (1) 
      (*this)[index]); // (2) 

} 

在實踐中,我們避免了全局狀態,所以這很少成爲問題。無論如何,檢查是微不足道的。

+0

+1。 – Tronic 2010-02-14 08:06:44