当成员值从指针更改为非指针时,C++常量问题

C++ const problems when member value is changed from pointer to non-pointer

本文关键字:指针 C++ 问题 常量 成员      更新时间:2023-10-16

我有两个类TestClassOtherClass,其中TestClass有一个名为m_otherClassOtherClass类型的成员变量。请注意,这未声明为常量。

在下面提供的最小示例中;当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()是常量(然后承诺不更改任何成员变量(,而setOtherMember()是非常量并且正在更改OtherClass的成员变量,然后间接更改m_otherClass对象?

但是,当m_otherClass是一个指针时,为什么这不会失败呢? 为什么编译器错误说将"const OtherClass"作为"this"参数传递失败,而m_otherClass尚未声明为const?

在大多数情况下,不允许 Const 限定的成员函数更改对象的成员状态。这意味着,每个不可变的成员都不能在此函数体中修改。在处理指针时,你只是说,你不会修改指针值,而不是点对本身。这是因为指针的恒定性不会在其点上传播

在即将出台的标准中,可以使用propagate_const来改变这种行为。

一个更简单的例子来演示差异。

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.

当你把 const 放在一个方法上时,你的所有数据成员都被视为 const。这就是为什么当您将 OtherClass 作为值时会出现错误,因为它变成了const OtherClass.

现在,当您使用OtherClass指针时,您会得到const std::unique_ptr<OtherClass>并且 const 仅适用于指针,而不适用于它指向的值。

但是

为什么当m_otherClass是一个指针时,这不会失败呢?

因为修改由常量指针指向的对象是常量正确的,只要它是指向非常量(如您的情况(的指针。

为什么编译器错误说将"const OtherClass"作为"this"参数传递失败,而m_otherClass尚未声明为const?

myMethod被宣布为常量。因此,this是指向 const 的指针。因此,无论由左值命名的对象是否为常量,左值this->m_otherClass也是常量。