在此代码中:
include<iostream>
using namespace std;
class A
{
public:
A(){} //constructor
void fun()
{
cout<<"in non-const fun"<<endl;
}
void fun() const
{
cout<<"in const fun"<<endl;
}
};
int main()
{
A obj;
A c_obj;
obj.fun()
c_obj.fun();
return 0;
}如果c_obj是class A的const对象,它就会调用fun()的const版本。non-const类对象可以调用fun()的任何版本,但是它们一直在调用non-const版本,直到non-const版本被删除/注释为止--为什么?
即使定义的顺序被更改,行为也保持不变(只是试图检查它是否影响到任何事情)。
发布于 2020-04-26 06:21:03
假设我们有一个类似OP描述的类A (即同一个成员函数的const版本和非const版本,分别命名为A::fun() const和A::fun() )。
这两个版本的不同之处在于,A::fun() const函数的规范是它不会在逻辑上更改所调用的对象的状态,而是允许A::fun()更改状态。
如果表达式/语句some_object.fun()调用A::fun() const,那么它将不会更改some_object的逻辑状态(即未指定为mutable的非static成员的值)。(假设没有未定义的行为)。
类似地,如果表达式some_object.fun()调用A::fun() (非const版本),那么some_object的状态可能在逻辑上被改变。
现在,我们需要了解实现(也称为编译器)在遇到表单some_object.fun()的表达式时应该做什么。由于有A::fun() const和A::fun(),所以有必要为实现应用一些标准来决定要调用哪一个。
第一个简单的例子是,some_object被声明为const (或者是对A的const引用)。
const A some_object;
some_object.fun();这个声明表达了程序员的意图,即some_object的逻辑状态不会改变。非const版本的fun()允许更改some_object的状态,因此它永远不是some_object.fun()的有效匹配--如果实现选择了这一点,那么它必须发出诊断(除其他外,这通常意味着代码不会编译)。所有这一切都意味着,在这种情况下,A::fun() const是唯一允许的选择。
第二种情况是,some_object没有被声明为const。
A some_object;
some_object.fun();声明表示程序员打算允许(或至少不允许)更改some_object的逻辑状态。由于A有一个const版本和一个非const版本的fun(),所以有三种可能的选择(名义上)已经写入了标准。
A::fun() const而不是A::fun() (非const版本)。不更改允许更改的对象是无害的。但是,此选项也消除了调用非const函数A::fun()的任何情况。因此,允许一个类同时拥有两个versions.A::fun() const上的A::fun()是没有意义的。这种选择没有坏处,因为如果更改是permitted.A::fun()和A::fun() const,则更改对象没有坏处。这给编译器带来了歧义,因为有两个同样有效的选项,并且没有理由选择一个而不是另一个,因此再次需要进行诊断。至于选项(1),这也意味着不存在调用非const函数的情况,因此允许类同时具有两个版本是没有意义的。以上选项(2)是标准所要求的。这意味着在所定义的情况下,可以调用A::fun()和A::fun() const (分别为非const和const对象)和选择中的最小不确定性。
对于两个选项(1)和(3),程序员提供A::fun()和A::fun() const都是没有意义的--或者标准甚至允许程序员提供这两个版本--因为在给定表单some_object.fun()的语句或表达式时,不存在调用非const版本的情况。要引入选项(1)或(3),标准中需要(可能是复杂的)一组附加子句,指定何时调用函数的非const版本。虽然C++标准化委员会以采用晦涩复杂的规则(可能过分)而闻名,但在这种情况下,它们似乎没有。
https://stackoverflow.com/questions/61435378
复制相似问题