在这样的声明中const的含义是什么?这个常数使我困惑。
class foobar
{
public:
operator int () const;
const char* foo() const;
};
在这样的声明中const的含义是什么?这个常数使我困惑。
class foobar
{
public:
operator int () const;
const char* foo() const;
};
当前回答
C++公共知识:基本中级编程中Const成员函数的含义给出了明确的解释:
类的非常量成员函数中此指针的类型X是X*常量。也就是说,它是指向非常数X的常数指针(见Const Pointers和Pointers to Const[7,21])。因为对象它所指的不是常量,可以修改。类型这在类X的常量成员函数中是常量X*const。那个是,它是指向常量X的常量指针。因为它是常量,不能修改。这就是常量和非常量成员函数之间的差异。
因此,在您的代码中:
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;
};
其他回答
我想补充一点。
也可以将其设置为常量和常量&&
So,
struct s{
void val1() const {
// *this is const here. Hence this function cannot modify any member of *this
}
void val2() const & {
// *this is const& here
}
void val3() const && {
// The object calling this function should be const rvalue only.
}
void val4() && {
// The object calling this function should be rvalue reference only.
}
};
int main(){
s a;
a.val1(); //okay
a.val2(); //okay
// a.val3() not okay, a is not rvalue will be okay if called like
std::move(a).val3(); // okay, move makes it a rvalue
}
请随意改进答案。我不是专家
const表示该方法承诺不会更改类的任何成员。即使对象本身被标记为const,也可以执行如此标记的对象成员:
const foobar fb;
fb.foo();
将是合法的。
看看C++中“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
}
阅读此处了解更多信息
当您将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
在常量对象中,只能调用常量方法。这种方法中的所有字段都被视为常量字段。最后一个问题产生了奇怪的影响:
指针变为const指针int*const,这与指向const const int*的指针不同。因此,您可以更改指针指向的对象,但不能使指针指向另一个对象。引用应该成为常量引用,但它始终是常量引用:不能将其重新初始化为另一个对象。但是,您可以再次更改引用引用的对象。