当调用来自同一个重载的非常量版本成员函数时,可以删除常量限定符吗

Is it okay to remove const qualifier when the call is from the same non-const version overloaded member function?

本文关键字:常量 删除 函数 成员 调用 同一个 重载 版本 非常      更新时间:2023-10-16

例如:

struct B{};
struct A {
const B& findB() const { /* some non trivial code */ }
// B& findB() { /* the same non trivial code */ }
B& findB() { 
const A& a = *this;
const B& b = a.findB();
return const_cast<B&>(b);
}
};

问题是,我希望避免在常量findB和非常量findB成员函数中重复相同的逻辑。

是的,您可以将对象强制转换为const,调用const版本,然后将结果强制转换为非const:

return const_cast<B&>(static_cast<const A*>(this)->findB());

只有当所讨论的对象最初不是声明为const时,丢弃const才是安全的。由于您所在的是一个非const成员函数,您可以知道这是一种情况,但这取决于实现。考虑:

class A {
public:
A(int value) : value(value) {}
// Safe: const int -> const int&
const int& get() const {
return value;
}
// Clearly unsafe: const int -> int&
int& get() {
return const_cast<int&>(static_cast<const A*>(this)->get());
}
private:
const int value;
};

一般来说,我的成员职能很短,所以重复是可以容忍的。有时,您可以将实现因素化为一个私有模板成员函数,并从两个版本调用该函数。

我认为,在这里使用强制转换是可以的,但如果你确实想避免它,你可以使用一些模板魔法:

struct B
{
B(const B&)
{
std::cout << "oops I copied";
}
B(){}
};
struct A {
public:
A(){}
A(const A&){ std::cout << "a is copied:(n";}
const B& findB() const { return getter(*this); }    
B& findB() { return getter(*this); }
private:
template <typename T, typename V>
struct same_const
{
typedef V& type;
};
template <typename T, typename V>
struct same_const<const T, V>
{
typedef const V& type;
};
template <typename T>
static typename same_const<T,B>::type getter(T& t) { return t.b;}
B b;
};
int main()
{
A a;
const A a_const;
const B& b1 = a.findB();
B& b2 = a.findB();
const B& b3 = a_const.findB();
//B& b4 = a_const.findB();
}