是否可以使父成员可变?(涉及IT技术)

5

出于好奇,

是否有可能将父类成员设置为mutable? 有没有合理的方法修改以下代码以使其编译?(保持foo()是一个const方法,并且在父类A中声明int a时不使用mutable

class A {
protected:
    int a;
};

class B : public A {
public:
    void foo() const {
        a = 10;
    }
};

1
那明显违反了 foo() 上的 const 承诺... 但是,如果你只是移除 const,那么在 A 中的 a 就没有修饰符了,但在 B 中有一个,这不就解决了你的问题吗? - Barry
不,我不知道为什么它被投票下降,除了表达某人对你想做的事情感到厌恶。这是不好的。停止。 - David
即使您更改了父部分,仍然会更改对象的一部分,这违反了const合同。 - NathanOliver
@NathanOliver 当然,但是如果 int a; 被声明为 mutable,你就可以这样做。 - Antonio
1
@Dave 这更多是出于好奇心提出的问题,今天我遇到了一个可能可以用这种方式解决的情况。但我认为,如果你需要这样的东西,那么意味着B不应该从A派生,而是B应该拥有A的一个实例。 - Antonio
2个回答

6

通常情况下,需要修改一个const变量意味着您在其他地方存在需要修复的设计错误……但如果您确实需要,可以使用const转换进行修改;例如:

const_cast<int&>(a) = 10;

考虑到您想把基类本身视为可变的,您可能需要在其他地方消除constness,例如通过制作一个成员函数来进行转换。

A& hack() const { return const_cast<B&>(*this); }

然后你可以实现foo如下:

hack().a = 10;

这种解决方法的缺点是将 const_cast 隐藏在函数调用后面,因此您需要确保阅读您代码的人知道您正在做一些“邪恶”的事情(例如通过为该函数选择一个合适的名称)。 然而,这个版本有一些优点:

  • 我认为代码更易读
  • 它不需要您重复执行此操作的对象的类型
  • 它确保您仅对 A 的成员执行此操作,而不是对 B 的成员执行此操作。

1
只是确认一下,如果我的 B 实例是 const,那么它会产生未定义的行为,对吗? - Antonio
1
@Antonio:我从未对此进行过足够的研究,不知道什么时候会出现什么问题,所以我只有模糊的想法。如果你想了解这方面的信息,你需要去其他地方查询。 - user1084944

1
据我所知,你不能这样做。这类似于问题是否可以从“const”基础派生,这更有可能被允许。
原则上可能是可行的,但会产生很多意外情况: 例如,这是否意味着您可以将B const引用传递给接受A非const引用的函数?
其他人说,在基类中使a成员可变会解决问题,但更接近您的问题的解决方案是使用组合而不是继承,如下所示:
struct B{
  mutable A m_a; 
  void foo() const {m_a.a = 10;} 
};

你可以添加operator A&() const{return m_a;},如果你需要(有限的)多态性。这也可能会有令人惊讶的行为。
它并不完全等同于假设的可变继承,但甚至可能更好。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接