在这样的声明中const的含义是什么?这个常数使我困惑。
class foobar
{
public:
operator int () const;
const char* foo() const;
};
在这样的声明中const的含义是什么?这个常数使我困惑。
class foobar
{
public:
operator int () const;
const char* foo() const;
};
当前回答
const限定符意味着可以对foobar的任何值调用这些方法。当您考虑对常量对象调用非常量方法时,就会出现不同。考虑您的foobar类型是否具有以下额外的方法声明:
class foobar {
...
const char* bar();
}
方法bar()是非常量的,只能从非常量值访问。
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);
其他回答
const限定符意味着可以对foobar的任何值调用这些方法。当您考虑对常量对象调用非常量方法时,就会出现不同。考虑您的foobar类型是否具有以下额外的方法声明:
class foobar {
...
const char* bar();
}
方法bar()是非常量的,只能从非常量值访问。
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);
布莱尔的答案是正确的。
但是请注意,有一个可变的限定符可以添加到类的数据成员中。任何标记的成员都可以在const方法中修改,而不违反const约定。
如果您希望对象记住某个特定方法被调用的次数,同时不影响该方法的“逻辑”常量,则可能需要使用这个(例如)。
在常量对象中,只能调用常量方法。这种方法中的所有字段都被视为常量字段。最后一个问题产生了奇怪的影响:
指针变为const指针int*const,这与指向const const int*的指针不同。因此,您可以更改指针指向的对象,但不能使指针指向另一个对象。引用应该成为常量引用,但它始终是常量引用:不能将其重新初始化为另一个对象。但是,您可以再次更改引用引用的对象。
当您将const关键字添加到方法时,此指针将实质上变为指向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
在非常量方法中,可以更改实例成员,这在常量版本中是无法做到的。如果将上面示例中的方法声明更改为下面的代码,则会出现一些错误。
void Foo()
{
counter++; //this works
std::cout << "Foo" << std::endl;
}
void Foo() const
{
counter++; //this will not compile
std::cout << "Foo const" << std::endl;
}
这并不完全正确,因为您可以将成员标记为可变的,然后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++; // This works because counter is `mutable`
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 << "Foo has been invoked " << ccc.GetInvocations() << " times" << std::endl;
}
它将输出
Foo
Foo const
Foo has been invoked 2 times
这些常量意味着如果“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
}
阅读此处了解更多信息