C++非const指针成员上的const方法

7
我想知道如何在const方法中保护一个非const指针成员变量。例如:
class B{
    public:
        B(){
            this->val=0;
        }

        void setVal(){
            this->val = 2;
        }

    private:
        int val;
};

class A{
    public:
        A():b(new B){}
        void changeMemberFromConstMethod() const{
            this->b->setVal();
        }
    private:
        B * b; // how to protect data pointed in A::changeMemberFromConstMethod
}

有没有可能在A::b方法中“保护”指向的数据? 经过多次网络研究,尚未找到满意的答案。 谢谢你的帮助。

6
“医生,我这样做会很疼。” - “那就不要那样做。” 没有人会扭曲你的手臂并强迫你在常量方法中调用 setVal。我想我不理解问题的本质。 - Igor Tandetnik
1
这只是一个示例。例如,这就像我想设置的保证,即不修改指向B数据的数据。 - Alex
如果你不想修改 *b,那就不要修改。我仍然无法理解困难的本质。 - Igor Tandetnik
1
首先感谢您的早期回复。我的问题性质是关于通过const进行语义保护的。如果b是一个对象,编译会失败,这是正常的。我想要保证这种行为。你明白吗?我知道如果我不想修改*b,我就不会去修改它。这只是举个例子。 - Alex
我猜他想看到执行上述代码时的错误信息。 - Michal Hosala
显示剩余2条评论
4个回答

11
也许是这样的内容:

类似于这样的东西:

template <typename T>
class deep_const_ptr {
  T* p_;
public:
  deep_const_ptr(T* p) : p_(p);

  T* operator->() { return p_;}
  const T* operator->() const { return p_;}
};

class A {
  deep_const_ptr<B> b = new B;
};

deep_const_ptrA的const方法中表现得像一个const T* const指针,在非const方法中则像T*。更详细的类定义留给读者自行完成。


很有趣!但是如何选择正确的运算符呢? - Alex
我差不多明白了。更精确地说,它是如何工作的(分辨率)?它将尝试第一个运算符,并查看返回值是否为const,然后找到正确的运算符?就这样? - Alex
1
不,重载决议(大多数情况下)不考虑返回类型。但它确实会考虑方法是否标记为“const”。当在const对象上调用时,非const方法不可行,因此只能使用const方法。当在非const对象上调用时,优先选择非const方法。 - Igor Tandetnik
非常感谢。你是怎么了解这些深层机制的呢?^^最后,你能看到我问题的目的和语义方式吗? - Alex

7
如果您更改了A的成员,则会从中删除该成员。
    B* b;

to

    B b;

那么你就能得到预期的结果。
class A{
    public:
        A() : b() {}

        void changeMemberFromConstMethod() const{
            this->b.setVal(); // This will produce a compiler error. 
        }
    private:
        B b;
}

6
您所面临的问题是const方法会使所有成员变量变为const。但在这种情况下,它会使指针变为const。具体来说,就好像您只有一个B * const b,这意味着一个指向(仍然可变的)B的常量指针。如果您没有将成员变量声明为const B * b(即指向常量B的可变指针),那么就无法防止这种行为。
如果您只需要一个const B,那么请按以下方式定义A
class A {
public:
    A() : b(new B) {}

    // This WILL give an error now.
    void changeMemberFromConstMethod() const { b->setVal(); }
private:
    const B* b;
}

但是,如果A的其他方法会改变B,那么你所能做的就是确保在A中的const方法中不会改变B


我同意你的看法。但是如果我设置: void changeMemberFromConstMethod(){b->setVal();} 另一方面,这将会失败。我希望const方法能够表明:const B * b const;你看到了吗? - Alex

2
尝试使用以下一般方法,在这种情况下保护通过指针引用的对象的const属性。
  1. Rename B *b

    B *my_pointer_to_b;
    

    And change the initialization in the constructor accordingly.

  2. Implement two stubs:

    B *my_b() { return b; }
    const B *my_b() const { return b; }
    
  3. Replace all existing references to b with my_b(), in the existing code. Going forward, in any new code, always use my_b() to return the pointer to b.

可变方法将获得指向B的非const指针;常量方法将获得指向B的const指针,并且重命名这一额外步骤可以确保所有现有代码都符合新的规则。


这是一种有趣的方法。但是有点扭曲^^。如何可能根据const或非const方法找到正确的方法呢? - Alex
1
一个const方法只能调用其他的const方法。在const方法中,“this”是一个常量指针,而不是可变指针。这实际上是一种相当常见的设计模式。 - Sam Varshavchik

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