'const' last在类的函数声明中的含义?

const 在这些声明中的含义是什么? const 让我困惑 .

class foobar
{
  public:
     operator int () const;
     const char* foo() const;
};

回答(7)

2 years ago

const 关键字添加到方法时, this 指针实际上将成为指向 const 对象的指针,因此您无法更改任何成员数据 . (除非您使用 mutable ,稍后会详细介绍) .

const 关键字是函数签名的一部分,这意味着您可以实现两个类似的方法,一个在对象是 const 时调用,另一个不是 .

#include <iostream>

class MyClass
{
private:
    int counter;
public:
    void Foo()
    { 
        std::cout << "Foo" << std::endl;    
    }

    void Foo() const
    {
        std::cout << "Foo const" << std::endl;
    }

};

int main()
{
    MyClass cc;
    const MyClass& ccc = cc;
    cc.Foo();
    ccc.Foo();
}

这将输出

Foo
Foo const

在非const方法中,您可以更改实例成员,而这些成员在 const 版本中无法执行 . 如果您将上面示例中的方法声明更改为以下代码,则会出现一些错误 .

void Foo()
    {
        counter++; //this works
        std::cout << "Foo" << std::endl;    
    }

    void Foo() const
    {
        counter++; //this will not compile
        std::cout << "Foo const" << std::endl;
    }

这不完全正确,因为您可以将成员标记为 mutable ,然后 const 方法可以更改它 . 它主要用于内部计数器和东西 . 解决方案就是下面的代码 .

#include <iostream>

class MyClass
{
private:
    mutable int counter;
public:

    MyClass() : counter(0) {}

    void Foo()
    {
        counter++;
        std::cout << "Foo" << std::endl;    
    }

    void Foo() const
    {
        counter++;
        std::cout << "Foo const" << std::endl;
    }

    int GetInvocations() const
    {
        return counter;
    }
};

int main(void)
{
    MyClass cc;
    const MyClass& ccc = cc;
    cc.Foo();
    ccc.Foo();
    std::cout << "The MyClass instance has been invoked " << ccc.GetInvocations() << " times" << endl;
}

哪个会输出

Foo
Foo const
The MyClass instance has been invoked 2 times

2 years ago

const意味着该方法承诺不会改变该类的任何成员 . 即使对象本身已标记为 const ,您_111781_的成员也会如此标记:

const foobar fb;
fb.foo();

是合法的 .

有关更多信息,请参见How many and which are the uses of “const” in C++? .

2 years ago

const 限定符意味着可以在 foobar 的任何值上调用这些方法 . 当您考虑在const对象上调用非const方法时会出现差异 . 考虑您的 foobar 类型是否具有以下额外方法声明:

class foobar {
  ...
  const char* bar();
}

方法 bar() 是非const的,只能从非const值访问 .

void func1(const foobar& fb1, foobar& fb2) {
  const char* v1 = fb1.bar();  // won't compile
  const char* v2 = fb2.bar();  // works
}

const 背后的想法是标记不会改变类的内部状态的方法 . 这是一个强大的概念,但在C中实际上并不强制执行 . 这更像是承诺而非保证 . 而且经常被打破并容易被打破的人 .

foobar& fbNonConst = const_cast<foobar&>(fb1);

2 years ago

这些const表示如果方法'with const'改变内部数据,编译器将出错 .

class A
{
public:
    A():member_()
    {
    }

    int hashGetter() const
    {
        state_ = 1;
        return member_;
    }
    int goodGetter() const
    {
        return member_;
    }
    int getter() const
    {
        //member_ = 2; // error
        return member_;
    }
    int badGetter()
    {
        return member_;
    }
private:
    mutable int state_;
    int member_;
};

考试

int main()
{
    const A a1;
    a1.badGetter(); // doesn't work
    a1.goodGetter(); // works
    a1.hashGetter(); // works

    A a2;
    a2.badGetter(); // works
    a2.goodGetter(); // works
    a2.hashGetter(); // works
}

有关更多信息,请阅读this

2 years ago

布莱尔的回答是正确的 .

但请注意,有一个 mutable 限定符可以添加到类的数据成员中 . 如此标记的任何成员都可以在 const 方法中进行修改,而不会违反 const Contract .

如果希望对象记住调用特定方法的次数,而不影响该方法的“逻辑”常量,则可能需要使用此(例如) .

2 years ago

C++ Common Knowledge: Essential Intermediate Programming中Const成员函数的含义给出了清楚的解释:

类X的非const成员函数中this指针的类型是X * const . 也就是说,它是一个指向非常数X的常量指针(参见Const Pointers和Pointers to Const [7,21]) . 因为它引用的对象不是const,所以可以修改它 . 类X的const成员函数中的类型是const X * const . 也就是说,它是一个指向常量X的常量指针 . 因为它引用的对象是const,所以它不能被修改 . 这是const和非const成员函数之间的区别 .

所以在你的代码中:

class foobar
{
  public:
     operator int () const;
     const char* foo() const;
};

你可以这样认为:

class foobar
{
  public:
     operator int (const foobar * const this) const;
     const char* foo(const foobar * const this) const;
};

2 years ago

当您在方法签名中使用 const 时(就像您所说的: const char* foo() const; ),您告诉编译器 this 指向的内存不能通过此方法更改(这里是 foo ) .