2010-02-14 67 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