从 const 对象访问非 const 方法

Accessing non const method from const object

本文关键字:const 方法 对象 访问      更新时间:2023-10-16

我有一个C++的例子,我尝试在通过 const getter 访问的类成员上设置一个属性。

#include <iostream>
struct prop
{
prop() : m_val {0} {}
int val() const { return m_val; }
void set_val(int v) { m_val = v; }
private:
int m_val;
};
struct base
{
virtual ~base() = default;
virtual prop property() const = 0;
virtual void set_property(prop p) = 0;
};
struct derived : public base
{
derived() : m_prop {prop {}} {}
prop property() const { return m_prop; }
void set_property(prop p) { m_prop = p; }
private:
prop m_prop;
};
int main()
{
base *d1 = new derived();
d1->property().set_val(2);
// prints 0
std::cout << "property val: " << d1->property().val() << 'n';
delete d1;
base *d2 = new derived();
auto p = d2->property();
p.set_val(2);
d2->set_property(p);
// prints 2
std::cout << "property val: " << d2->property().val() << 'n';
delete d2;
return 0;
}

我希望这会给我一个错误d1->property().set_val(2);因为property()方法const并且应该给我一个没有set_val方法的const prop对象。但是这编译没有任何错误,并且行d1->property().set_val(2);实际上并没有更改val,如cout行所示。有人可以解释一下我错过了什么吗?

编辑:我现在了解property()返回非常量和按值的问题,以及为什么这不会给出编译器错误并且不会更改d1。在我的用例中,最好的解决方案是使property的返回值prop const&

d1->property().set_val(2);实际上并没有改变val

因为property()按值返回,这意味着property()返回的是从数据成员m_prop复制的临时对象。然后set_val在立即销毁的临时对象上调用。

因为property()方法const并且应该给我一个const prop对象

不。将返回类型声明为prop,然后它将返回一个非常量prop。在constproperty()中,数据成员m_prop变得const,它被复制到返回的非常量对象。返回类型不会变为const

我认为您应该将返回类型更改为const prop&(在basederived类中(。然后,您将获得预期的错误。例如

const prop& property() const { return m_prop; }

property返回m_prop的副本,这是一个可修改的值,尽管是临时的。 因此,您不会对dl进行任何更改,打印出时的值仍将是原始值。

如果希望property()成员函数返回const prop对象,请指定它这样做:

struct base{
virtual const prop property() const=0;
};

就目前而言,您将获得一个非constprop对象,它是该属性的副本。您可以愉快地设置该对象的值,但它不会影响存储的属性值。

该方法const只是意味着调用它不会改变您调用它的对象。

您从方法(按值(返回的对象是一个全新的对象,您可以对它执行所需的操作。它与你从哪个对象获取它(除了是getter返回的内容的副本(或你为获取它而调用的函数的const性无关。