Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;非常量指针成员上的常量方法_C++_Pointers_Object_Methods_Constants - Fatal编程技术网

C++ C++;非常量指针成员上的常量方法

C++ C++;非常量指针成员上的常量方法,c++,pointers,object,methods,constants,C++,Pointers,Object,Methods,Constants,我想知道如何通过const方法保护非const指针成员不受对象的影响。例如: class B{ public: B(){ this->val=0; } void setVal(){ this->val = 2; } private: int val; }; class A{ public: A():b(new B

我想知道如何通过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数据? 经过大量的网络研究,目前还没有令人满意的结果


感谢您的帮助。

如果您从

    B* b;

然后您将获得预期的行为

class A{
    public:
        A() : b() {}

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

问题是
const
方法使所有成员变量
const
。但是,在这种情况下,它会使指针
常量
。具体地说,就好像你所拥有的就是
B*const B
,这意味着一个指向(仍然)可变
B
的常量指针。如果不将成员变量声明为
const B*B
,(即指向常量
B
)的可变指针,则无法防止这种行为

class A{
    public:
        A() : b() {}

        void changeMemberFromConstMethod() const{
            this->b.setVal(); // This will produce a compiler error. 
        }
    private:
        B b;
}
如果您只需要一个
常数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
,那么您所能做的就是确保
B
不会在
A

常量中变异,比如:

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;
};
模板
类深常数{
T*p_;
公众:
深常数ptr(T*p):p(p);
T*运算符->(){return p_;}
常量T*运算符->()常量{return p_;}
};
甲级{
深常数b=新b;
};

deep_const_ptr
a
的常量方法中的行为类似于
const T*const
指针,在非常量方法中的行为类似于
T*
。进一步充实类是读者的一项练习。

在这种情况下,尝试使用以下通用方法来保护通过指针引用的对象的常量

  • 重命名为B*B

    B *my_pointer_to_b;
    
    并相应地更改构造函数中的初始化

  • 实现两个存根:

    B *my_b() { return b; }
    const B *my_b() const { return b; }
    
  • 用现有代码中的my_b()替换对b的所有现有引用。接下来,在任何新代码中,始终使用my_b()返回指向b的指针


  • 可变方法将获得指向B的非常量指针;const方法将得到一个指向B的const指针,重命名的额外步骤确保所有现有代码都必须遵守新的规则。

    “医生,我这样做很痛苦”-“所以不要这样做。”
    这不像是有人扭动你的手臂,强迫你从const方法调用
    setVal
    。我想我不明白这个问题的本质,只是举个例子。例如,它就像我要设置的保证,即不修改指向的B数据。如果你不想修改
    *B
    ,那么就不要修改。我仍然无法理解困难的本质。首先感谢您的早期回答。我的问题的本质是关于通过const进行语义保护。如果b是一个对象,编译失败,这是正常的。我想保证这种行为。你看到了吗?我知道如果我不想修改*b我不会。只是举个例子。我猜他想看到执行上述代码的错误消息。我同意你的看法。但是如果我设置:void changemberfromConstMethod(){b->setVal();},另一方面这将失败。我希望const方法说:const B*B const;你看,这是一个有趣的方法。但它有点扭曲。如何根据const或not method找到正确的方法?const方法只能调用其他const方法。在常量方法中,“this”是常量指针,而不是可变指针。这确实是一种相当常见的设计模式。它很有趣!但是如何选择正确的操作符呢?我几乎明白了。它如何更精确地工作(分辨率)。它将尝试第一个运算符,并查看返回值是否为常量,并将找到正确的另一个运算符?就这样?不,重载解析(大多数情况下)不会查看返回类型。但它确实会检查该方法是否标记为
    const
    。在常量对象上调用时,非常量方法不可行,因此只能使用常量方法。在非常量对象上调用时,首选非常量方法。非常感谢。你是怎么知道这些深层力学的最后,你明白我问题的目的和语义方式了吗?