【问题标题】:const/non-const objects calling const/non-const functions调用 const/non-const 函数的 const/non-const 对象
【发布时间】:2020-04-26 03:15:29
【问题描述】:

在这段代码中:

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 对象,它将调用const 版本的fun()。 non-const 类对象可以调用fun() 的任何版本,但它们一直调用non-const 版本,直到并且除非non-const 版本被删除/注释 - 为什么?

即使定义的顺序改变了,行为也保持不变(只是试图检查它是否影响任何东西)。

【问题讨论】:

标签: c++


【解决方案1】:

假设我们有一个类 A,就像 OP 所描述的那样(即具有相同成员函数的 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(或者是const 对A 的引用)。

const A some_object;
some_object.fun();

此声明表达了程序员的意图,即some_object 的逻辑状态不会改变。允许fun() 的非const 版本更改some_object 的状态,因此它永远不是some_object.fun() 的有效匹配 - 如果实现选择这个,它必须发出诊断(其中,其中其他的东西,通常意味着代码不会编译)。所有这一切都意味着A::fun() const 是这种情况下唯一允许的选择。

第二种情况是some_object没有声明为const。

A some_object;
some_object.fun();

该声明表达了程序员允许(或至少不禁止)更改some_object 的逻辑状态的意图。由于A 具有const 和非const 版本的fun(),因此标准中可能(理论上)规定了三种可能的选择。

  1. 更喜欢调用A::fun() const 而不是A::fun()(非const 版本)。不更改允许更改的对象没有害处。然而,这个选项也消除了非const 函数A::fun() 将被调用的任何情况。因此,允许一个类同时具有两个版本是没​​有意义的。
  2. 宁愿打电话给A::fun() 而不是A::fun() const。这种选择没有害处,因为在允许更改的情况下更改对象也没有害处。
  3. 认为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++ 标准化委员会以接受晦涩难懂和复杂的规则(可能过度)而著称,但在这种情况下似乎没有。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多