8

给定这样的声明:

class A {
public:
    void Foo() const;
};

这是什么意思?

谷歌出现了这个:

如果成员函数可以对 const (this) 对象进行操作,则应在其后使用 const 关键字声明成员函数。如果函数没有声明为 const,则 in 不能应用于 const 对象,并且编译器会给出错误信息。

但我觉得这有点令人困惑;有谁能把它说得更好吗?

谢谢。

4

7 回答 7

12

考虑你的类的变化A

class A {
public:
    void Foo() const;
    void Moo();

private:
    int m_nState; // Could add mutable keyword if desired
    int GetState() const   { return m_nState; }
    void SetState(int val) { m_nState = val; }
};

const A *A1 = new A();
A *A2 = new A();

A1->Foo(); // OK
A2->Foo(); // OK

A1->Moo(); // Error - Not allowed to call non-const function on const object instance
A2->Moo(); // OK

函数声明中的const关键字向编译器表明该函数有合同义务不修改A. 因此,您无法在const内部调用非函数,A::Foo也无法更改成员变量的值。

为了说明,Foo()可能不会调用A::SetState,因为它被声明为 non- constA::GetState但是可以,因为它是显式声明const的。除非使用关键字声明,否则成员m_nState也不能更改mutable

这种用法的一个例子const是“getter”函数获取成员变量的值。

@1800 信息:我忘了可变的!

关键字指示编译器接受对成员变量的mutable修改,否则会导致编译器错误。当函数需要修改状态但无论修改如何都认为对象在逻辑上一致(常量)时使用它。

于 2008-09-08T02:37:08.667 回答
5

这不是一个答案,只是一个侧面评论。强烈建议尽可能多地声明变量和常量const

  1. 这会将您的意图传达给您班级的用户(甚至/尤其是您自己)。
  2. 编译器会让你诚实面对这些意图。-- 即,它就像编译器检查的文档。
  3. 根据定义,这可以防止您未预料到的状态更改,并且可能允许您在方法中做出合理的假设。
  4. const有一种通过代码传播的有趣方式。因此,const尽早并尽可能多地开始使用是一个非常好的主意。决定const在游戏后期开始对代码进行修改可能会很痛苦(容易,但很烦人)。

如果您使用的是静态语言,编译时检查是一个好主意,尽可能多地使用它们……这实际上只是另一种测试。

于 2008-09-08T02:52:00.830 回答
3

带限定符的函数const不允许修改任何成员变量。例如:

class A
{
    int x;
    mutable int y;

    void f() const
    {
      x = 1; // error
      y = 1; // ok because y is mutable
    }
};
于 2008-09-08T02:27:33.993 回答
2

C++ 对象可以声明为 const:

const A obj = new A();

当一个对象是 const 时,可以在该对象上调用的唯一成员函数是声明为 const 的函数。将对象设为 const 可以解释为将对象设为只读。const 对象不能更改,即对象的任何数据成员都不能更改。声明成员函数 const 意味着不允许该函数对对象的数据成员进行任何更改。

于 2008-09-08T02:30:22.537 回答
2

从经验中建议的两个最佳实践:

(1)尽可能声明 const 函数。起初,我发现这只是额外的工作,但后来我开始将我的对象传递给具有 f(const Object& o) 之类签名的函数,然后编译器突然在 f 中的一行,例如 o.GetAValue(),因为我没有将 GetAValue 标记为 const 函数。这会让您感到惊讶,尤其是当您将某些东西子类化并且不将您的虚拟方法版本标记为 const 时 - 在这种情况下,编译可能会在您之前从未听说过的为基类编写的某些函数上失败。

(2)在可行的情况下避免使用可变变量。一个诱人的陷阱可能是允许读取操作改变状态,例如,如果您正在构建一个执行惰性或异步 i/o 操作的“智能”对象。如果你可以只用一个小的可变变量(如布尔值)来管理它,那么根据我的经验,这是有道理的。但是,如果您发现自己将每个成员变量标记为可变以保持某些操作 const,那么您就违背了 const 关键字的目的。可能出错的是一个认为它没有改变你的类的函数(因为它只调用 const 方法)我在你的代码中调用了一个错误,甚至可能需要付出很多努力才能意识到这个错误在你的类中,

于 2008-09-12T12:43:25.803 回答
2

const 有一种通过代码传播的有趣方式。因此,尽早并尽可能多地开始使用 const 是一个非常好的主意。决定在游戏后期开始对代码进行 const 化可能会很痛苦(容易,但很烦人)。

此外,如果应该是 const 的方法不是,您将很容易遇到问题!这也将渗透到代码中,并使其变得越来越糟。

于 2008-09-12T22:58:36.013 回答
1

这将导致该方法无法更改对象的任何成员变量

于 2008-09-08T02:23:11.837 回答