c++ - 调用 const/non-const 函数的 const/non-const 对象
问题描述
在这段代码中:
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
是它的一个const
对象,class A
它将被const
称为fun()
. 一个non-const
类对象可以调用任何版本,fun()
但他们一直调用该non-const
版本,直到并且除非该non-const
版本被删除/注释 - 为什么?
即使定义的顺序改变了,行为也保持不变(只是试图检查它是否影响任何东西)。
解决方案
假设我们有一个A
类似于 OP 所描述的类(即,具有相同成员函数的一个const
和非版本,分别命名为和。const
A::fun() const
A::fun()
两个版本的区别在于A::fun() const
函数的规范是它不会在逻辑上改变它被调用的对象的状态,但这A::fun()
是允许的。
如果一个表达式/语句some_object.fun()
调用A::fun() const
,那么它不会改变 的逻辑状态(即static
未指定为 的非成员的值mutable
)some_object
。(假设不存在未定义的行为)。
类似地,如果表达式some_object.fun()
调用A::fun()
(非const
版本),那么状态some_object
可能会在逻辑上改变。
现在,我们需要看看实现(又名编译器)在遇到 form 的表达式时应该做什么some_object.fun()
。由于两者都有A::fun() const
和A::fun()
,因此有必要为实现应用一些标准来决定调用哪一个。
第一个简单的案例是some_object
声明const
的(或者是const
对 an 的引用A
)。
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
既有 a版本又有const
非const
版本,fun()
因此(理论上)可以在标准中包含三种可能的选择。
- 更喜欢调用
A::fun() const
(A::fun()
非const
版本)。不更改允许更改的对象没有害处。但是,此选项也消除了任何可能调用非const
函数的情况。A::fun()
因此,允许一个类同时具有两个版本是没有意义的。 - 更喜欢调用
A::fun()
.A::fun() const
这种选择没有害处,因为在允许更改时更改对象没有害处。 - 认为
A::fun()
并A::fun() const
成为同样优秀的候选人。这给编译器带来了歧义,因为有两个同样有效的替代方案,没有理由偏爱一个,因此再次需要诊断。至于选项(1),这也意味着在任何情况下const
都不会调用非函数,因此允许一个类同时具有两个版本是没有意义的。
上面的选项(2)是标准要求的。这意味着存在定义的情况,其中每个A::fun()
和A::fun() const
可以被称为(分别是非const
和const
对象)并且选择的不确定性最小。
对于选项 (1) 和 (3),程序员提供两者A::fun()
和A::fun() const
- 或标准甚至允许程序员提供两个版本 - 因为没有任何情况下非const
版本将是当给定一个语句或表达式时调用some_object.fun()
。要引入选项 (1) 或 (3),标准中需要有一组(可能很复杂)附加条款,指定何时const
调用函数的非版本。虽然 C++ 标准化委员会以接受晦涩难懂和复杂的规则(可能过度)而著称,但在这种情况下似乎没有。
推荐阅读
- java - 几乎递增的序列java
- vb.net - 获取 Panel 控件中特定文本框(不是全部)的文本
- azure - Umbraco 部署到 Azure
- vb.net - 基于cmd输出的VB.NET进度条
- mysql - 优化多连接 SQL
- java - Firebase 数据库用 setValue 覆盖
- php - Steam Web API - 解析 GetUserStatsForGame 的 JSON 结果
- python - 如何将 excel 或 csv 文件转换为 django 中的 html 表?
- r - ggplot barchart“错误:提供给连续刻度的离散值”在重新排序计数的 x 轴上
- css - 你知道为什么关闭按钮和关闭图标没有出现在大屏幕上吗?