我有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;
}
我不想允许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;
问题是tree
内部应该能够修改节点并处理像set_parent
这样的方法。但由于工厂只返回const
个节点,我最终将find
的另一个重载(非常量版本)添加到工厂中。
tree_node* find(const std::string& text);
我想知道这是处理这类问题的正确方法吗?我看到代码在const和非const版本中都是重复的。
有什么想法..?
答案 0 :(得分:7)
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
}
通常它都会在一条线上。你也可以为它做一个实用工具。
请注意:如果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)
}
在实践中,我们避免全球状态,所以这很少是一个问题。无论如何,检查是微不足道的。
答案 1 :(得分:3)
不幸的是,C ++没有工具(除了宏)来消除函数重载中的源代码重复,这些重载看起来大致相同但是const的不同。但是,您可以使用另一个函数const_cast
实现其中一个函数。