金庆的专栏

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  423 随笔 :: 0 文章 :: 454 评论 :: 0 Trackbacks
用const方法更改非mutable成员

以下代码中,SetValConst()是const类A的const方法,却能更改A的非mutable成员。
涉及的C++概念:bitwise constness

class B;

class A
{
public:
    A();
    void SetVal(int nVal) {m_nVal = nVal;}
    void SetValConst(int nVal) const;    // But will modify m_nVal!
private:
    int m_nVal;    // non-mutable!
    B* m_pB;
};

class B
{
public:
    B(A* pA): m_pA(pA) {};
    void SetValOfA(int nVal)
    {
        m_pA->SetVal(nVal);
    }
private:
    B();
    A* m_pA;
};

A::A(): m_nVal(0), m_pB(new B(this))
{
}

void A::SetValConst(int nVal) const
{
    m_pB->SetValOfA(nVal);
}

int main()
{
    const A a;
    a.SetValConst(1);
    return 0;
}


posted on 2008-08-27 19:10 金庆 阅读(624) 评论(10)  编辑 收藏 引用 所属分类: 1. C/C++

评论

# re: 用const方法更改非mutable成员[未登录] 2008-08-28 09:53 raof01
昨天看见你给我的评论,今天就看见这个了。:)
这里并不是打破了bitwise constness。如图:
obj1
 ------
| data1|
|------|      obj2
|ptr---+--> -----------------
 ------    |Can be modified  |
           |without breaking |
           |bitwise constness|
            -----------------  回复  更多评论
  

# re: 用const方法更改非mutable成员[未登录] 2008-08-28 09:54 raof01
对于obj1来说,通过ptr修改obj2并没有修改obj1所引用的内存区。这个obj1的bit pattern不变。  回复  更多评论
  

# re: 用const方法更改非mutable成员 2008-08-30 20:06 金庆
我发现一个问题:
B * pB(new B(&a));
肯定不行,因为&a是const A *,不能转成A*。
但是const A a的构造函数中却可以用this构造B。
为什么const A a构造时,this 指针不是 const A*,而是 A* 呢?
  回复  更多评论
  

# re: 用const方法更改非mutable成员[未登录] 2008-09-01 10:16 raof01
就算构造const对象,也需要修改这个内存啊。对象构造完成const才能起作用,否则怎么构造/初始化?  回复  更多评论
  

# re: 用const方法更改非mutable成员 2008-09-01 16:44 sPhinX
const能保证的更多的是语义上的,而不是能完全保证成员变量不被修改,换句话说,const的保证是由写程序的人来保证,而不是编译器。  回复  更多评论
  

# re: 用const方法更改非mutable成员 2008-09-01 16:47 sPhinX
你所说的问题是因为你用了一个未定义的行为,我用VS2003编译会有下面的警告:

编译器警告(等级 1 和等级 4)C4355

错误消息
“this”: 用于基成员初始值设定项列表


this 指针仅在非静态成员函数中有效。它不能在基类的初始值设定项列表中使用。

基类构造函数和类成员构造函数先于 this 构造函数被调用。实际上,您已将指向非构造对象的指针传递给了另一个构造函数。如果那些其他的构造函数访问此构造函数上的任何成员或调用其上的成员函数,结果将是不确定的。应一直不使用 this 指针,直到所有构造都已完成。

  回复  更多评论
  

# re: 用const方法更改非mutable成员 2008-09-01 16:48 sPhinX
上面说错了,是VS2005,不是VS2003。  回复  更多评论
  

# re: 用const方法更改非mutable成员 2008-09-02 08:48 金庆
@sPhinX
有道理。
gcc 怎么没这个警告呢?
但在构造函数中不用this怎么初始化B呢?  回复  更多评论
  

# re: 用const方法更改非mutable成员[未登录] 2008-09-02 09:56 raof01
@sPhinX
M$的东西与GCC有差异。各自实现了标准的大部分,有自己的扩展。对于标准中“it depends”的东西就形态各异了。

另外,const的保证是由编译器来保证的,你看我画的那个图。  回复  更多评论
  

# re: 用const方法更改非mutable成员 2008-10-23 11:06 Ordie
我觉得只能这样说,博主的这种用法在实际编程中确实有可能出现,但如果真的要这么用,请不要用在const对象上,因为这样是危险的。

我们都知道在构造函数没有执行完的时候,对象处在未完全初始化的状态。而且我们也要清楚一点,构造函数是一定要改动对象的成员的(因为要初始化),所以构造函数一定不会是const的,所以构造函数里的this指针也不会是const的,这对于const对象和非const对象是一样的。那么,如果真的要在构造的时候就用this指针,这时候我们是无法知道这个对象是不是const的,所以我觉得,唯一的办法就是既然无法分辨,我们就当它是非const的,而我们也希望它是非const的,否则就会出问题。  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理