我在C ++中有一个数据结构类,它有一个对象的访问器(可能很大),我有使用这个访问器的const和非const方法,所以我需要重载它。我正在寻找下面代码的批判 - 也许有办法完成同样的事情更清洁?
我理解它的方式,有两种方法可以实现这一点,而不会在以下情况下复制访问器中的代码,方法是get()。我不确定这两种方法中是否存在严重问题,并且我希望得到一些指导。
我喜欢方法A因为:
我不喜欢方法A,因为:
我喜欢方法B因为:
我不喜欢方法B,因为:
这是两种情况的(最小)示例代码。
/**
* 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
}
答案 0 :(得分:2)
成员函数的constness应根据以下问题来决定:是在上下文中用于修改对象的成员函数吗?(成员直接修改对象,或返回引用/指向内部数据的指针,以便外部调用者可以修改对象)。如果是,请将其设为非常量,否则使其成为常量。
编译器将正确地选择仅在constness上有所不同的重载。但是,在重载解析中不使用返回类型。此外,返回按值/按引用应仅根据预期成本和您要返回的目标所有权来决定。幸运的是,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
};