我有两个类TestClass
和OtherClass
,其中TestClass
的类型为OtherClass
的成员变量名为m_otherClass
。请注意,不声明为常量。
在下面提供的最小示例中;当m_otherClass
是一个指针时,则所有内容都会编译并运行良好。如果将其更改为非指针,则会出现编译器错误(在最小的示例中将更改注释掉了):
“在常量对象上调用了非常量函数'setOtherMember'”
错误:将“ const OtherClass”作为“ this”参数传递会丢弃限定符[-fpermissive] m_otherClass.setOtherMember();
#include <iostream>
#include <memory>
class OtherClass {
public:
void setOtherMember() {
m_otherMember = 2;
std::cout << "Other member is now 2" << std::endl;
}
private:
int m_otherMember = 0;
};
class TestClass {
public:
TestClass(): m_otherClass(std::make_unique<OtherClass>())
// TestClass()
{}
void myMethod() const {
m_otherClass->setOtherMember();
// m_otherClass.setOtherMember();
}
private:
std::unique_ptr<OtherClass> m_otherClass;
// OtherClass m_otherClass; // If changing to this I get the error!!
};
int main() {
TestClass testClass;
testClass.myMethod();
return 0;
}
这是因为myMethod()
是const(然后保证不更改任何成员变量),而setOtherMember()
是非const并正在更改OtherClass
的成员变量,然后还间接地m_otherClass
对象?
但是如果m_otherClass
是指针,为什么这不会失败?
为何编译器错误说在未m_otherClass
声明为const的情况下将'const OtherClass'传递为'this'参数失败了?
答案 0 :(得分:3)
在大多数情况下,不允许使用const合格的成员函数来更改对象的成员状态。这意味着不能在该功能体中修改每个不可变的成员。在处理指针时,您只是说,您将不会修改指针值,而不是指针对象本身。这是因为指针的常量性不会在其指针上传播。
在即将发布的标准中,可以使用propagate_const来更改此行为。
答案 1 :(得分:2)
一个更简单的示例来说明差异。
struct Foo { int m; };
const Foo f = {10};
f.m = 20; // Not allowed since modifying f.m modifies f.
struct Bar { int* p; };
int i = 10;
int j = 20;
const Bar b = {&i};
b.p = &j; // Not allowed since modifying b.p modifies b.
*(b.p) = j; // Allowed since it does not change b or b.p. It changes the value
// of what b.p points to.
答案 2 :(得分:1)
但是如果
m_otherClass
是指针,为什么这不会失败?
因为修改const指针指向的对象是const正确的,只要它是指向非const的指针(例如您的情况)即可。
为什么未将m_otherClass声明为const时,编译器错误为什么将'const OtherClass'传递为'this'参数失败?
myMethod
被声明为const。因此this
是指向const的指针。因此,不管由左值命名的对象是否为const,左值this->m_otherClass
都是const。
答案 3 :(得分:1)
将const放在方法上时,所有数据成员都被视为const。这就是为什么将OtherClass作为值时会出现错误的原因,因为它变成了const OtherClass
的值。
现在,当您使用指针OtherClass
时,会得到const std::unique_ptr<OtherClass>
,而const仅适用于指针,而不适用于其指向的值。