首页 > 解决方案 > 调用 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版本被删除/注释 - 为什么?

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

标签: c++

解决方案


假设我们有一个A类似于 OP 所描述的类(即,具有相同成员函数的一个const和非版本,分别命名为和。constA::fun() constA::fun()

两个版本的区别在于A::fun() const函数的规范是它不会在逻辑上改变它被调用的对象的状态,但这A::fun()是允许的。

如果一个表达式/语句some_object.fun()调用A::fun() const,那么它不会改变 的逻辑状态(即static未指定为 的非成员的值mutablesome_object。(假设不存在未定义的行为)。

类似地,如果表达式some_object.fun()调用A::fun()(非const版本),那么状态some_object可能会在逻辑上改变。

现在,我们需要看看实现(又名编译器)在遇到 form 的表达式时应该做什么some_object.fun()。由于两者都有A::fun() constA::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版本又有constconst版本,fun()因此(理论上)可以在标准中包含三种可能的选择。

  1. 更喜欢调用A::fun() constA::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可以被称为(分别是非constconst对象)并且选择的不确定性最小。

对于选项 (1) 和 (3),程序员提供两者A::fun()A::fun() const- 或标准甚至允许程序员提供两个版本 - 因为没有任何情况下非const版本将是当给定一个语句或表达式时调用some_object.fun()。要引入选项 (1) 或 (3),标准中需要有一组(可能很复杂)附加条款,指定何时const调用函数的非版本。虽然 C++ 标准化委员会以接受晦涩难懂和复杂的规则(可能过度)而著称,但在这种情况下似乎没有。


推荐阅读