与C ++中的方法一起使用时,const运算符是什么意思?

时间:2020-03-05 18:49:07  来源:igfitidea点击:

给定这样的声明:

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

这是什么意思?

Google证明了这一点:

Member functions should be declared with the const keyword after them if they can operate on a const (this) object. If the function is not declared const, in can not be applied to a const object, and the compiler will give an error message.

但是我发现这有些令人困惑;有人可以把它放在更好的状态吗?

谢谢。

解决方案

回答

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

回答

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

class A
{
    int x;
    mutable int y;

    void f() const
    {
      x = 1; // error
      y = 1; // ok because y is mutable
    }
};

回答

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

const A obj = new A();

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

回答

考虑类" 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状态。因此,我们将无法在A :: Foo中调用非const函数,也无法更改成员变量的值。

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

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

@1800 Information: I forgot about mutable!

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

回答

这不是答案,只是附带评论。强烈建议尽可能声明变量和常量" const"。

  • 这可以将意图传达给班级的用户(甚至/尤其是我们自己)。
  • 编译器将使我们对这些意图保持诚实。 -即就像编译器检查过的文档一样。
  • 根据定义,这可以防止发生我们意料之外的状态更改,并且可能允许我们在使用方法时做出合理的假设。
  • const具有一种有趣的方式来传播代码。因此,尽早并尽可能多地开始使用const是一个非常好的主意。决定在游戏后期开始使用" const"对代码进行编码可能很痛苦(容易,但很烦人)。

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

回答

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

(1)尽可能声明const函数。最初,我发现这只是多余的工作,但后来我开始将我的对象传递给具有f(const Object&o)等签名的函数,然后突然编译器将f。我没有将GetAValue标记为const函数。这可能会让我们感到惊讶,特别是当我们将某些子类化并且不将虚拟方法的版本标记为const时,在这种情况下,编译可能会针对我们为基类编写之前从未听说过的某些函数而失败。

(2)在可行时避免使用可变变量。一个诱人的陷阱可能是允许读取操作更改状态,例如,如果我们要构建一个执行惰性或者异步I / O操作的"智能"对象。如果我们仅可以使用一个小的可变变量(例如bool)来管理它,那么根据我的经验,这是有道理的。但是,如果我们发现自己将每个成员变量都标记为可变的,以保持某些操作const,那么我们将违反const关键字的目的。可能出问题的是,一个函数认为它没有改变类(因为它仅调用const方法),因此我在代码中调用了一个错误,甚至可能需要花费很多精力才能意识到这个错误在类中另一个编码器(正确地)假定数据为const,因为他或者她仅调用const方法。

回答

const has a funny way of propagating through your code. Thus, it's a really good idea to start using const as early and as often as possible. Deciding to start const-ifying your code late in the game can be painful (easy, but annoying).

此外,如果不是应该使用const的方法,我们将很容易遇到问题!这也将遍历代码,并使它变得越来越糟。