我有3节课.它是最简单的形式,看起来像,
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;
}
Run Code Online (Sandbox Code Playgroud)
我不想让用户tree修改tree_node像方法返回的方法find_node.所以我改变了,find_node并且tree_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;
Run Code Online (Sandbox Code Playgroud)
问题是tree内部应该能够修改节点并处理类似的方法set_parent.但由于工厂只返回const节点,我最终在工厂中添加了另一个重载(非const版本)find.
tree_node* find(const std::string& text);
Run Code Online (Sandbox Code Playgroud)
我想知道这是处理这类问题的正确方法吗?我看到代码在const和非const版本中都是重复的.
有什么想法吗..?
Scott Meyers的书" Effective C++ "中的第3项演示了一种删除此代码重复的方法.基本上,在你的非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
}
Run Code Online (Sandbox Code Playgroud)
通常它都会在一条线上.您也可以为它制作一个实用程序.
请注意一个警告:如果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)
}
Run Code Online (Sandbox Code Playgroud)
在实践中,我们避免全球状态,所以这很少是一个问题.无论如何,检查是微不足道的.