C ++ Constness问题

时间:2011-03-07 15:45:40

标签: c++ const

关于是否让班级成员保持不变,我有一个问题。让我举个例子。

#include <iostream>
class ValueClass
{
    int ival;
public:
    void set(int i) {ival = i;}
    int get() {return ival;}
};

class XXX;

class ABC
{
    ValueClass vc;  
public:
    int getval() const {return vc.get() ;}  
friend class XXX;
};

class XXX
{
    std::vector<ABC> abclist;
    void Invalidate()
    {
    // Iterates through abclist and modifies ValueClass members.
    // e.g. abclist[i].vc.set(i);
    }
};

class QWE
{
    const ABC & abc; 
public:
    QWE(const ABC & abc_): abc(abc_) { }
    const ABC & getABC() { return abc; } 
};

int main()
{
    ABC abc;
    QWE qwe(abc);

    std::cout << qwe.getABC().getval()  << "\n"; // Compiler error
}

我的ABC类包含一个ValueClass实例,它负责为int值设置getter和setter。 QWE类也有一个ABC成员,我需要获得此成员。我被告知将abc作为非常量返回是一种非常糟糕的做法。但问题来了,我不能在const vc函数中使用非const int getval()而我根本无法使它成为const因为在另一个线程XXX::Invalidate()中被调用。此函数根据某些传入数据更改ValueClass中的数据 显然我的设计有问题,我不能责怪C ++语言。我该如何解决这个问题?

3 个答案:

答案 0 :(得分:3)

在ValueClass中创建get()const

  class ValueClass
  {
      int ival;
    public:
      void set(int i) {ival = i;}
      int get() const {return ival;} // make get const
  };

可能应该为getABC做同样的事情

  const ABC & getABC() const { return abc; } 

这意味着此方法不会更改调用它的对象。

答案 1 :(得分:1)

正如其他人所说,访问者应该是const限定的。作为一般规则,如果某些可以是const限定的,那么 应该是const限定的(当然有一些例外,例如函数的返回类型)按值返回不应该是const限定的,尽管通常并不重要。)

但是,编写的代码存在另一个问题:它很容易被错误地使用,并且意外地丢失了对象生命周期。考虑您是否在qwe中声明main()为:

QWE qwe(ABC());

ABC()构造一个临时ABC对象并将其传递给QWE构造函数。由于构造函数参数abc_const ABC&,因此它将绑定到该临时对象。然后,通过初始化程序abc将成员引用abc(abc_)绑定到临时对象。然后构造函数返回。

构造函数返回后,临时ABC对象被销毁,qwe.abc是悬空引用:它不再引用对象。

如果一个类要挂在你传递给它的引用上,你应该更喜欢使用指针作为参数类型:这样,你就更清楚你必须关注潜在的生命周期问题。另外,引用类类成员通常比它们的值更糟糕,因为它们使类不可赋值(因为引用本身不可赋值)。

答案 2 :(得分:0)

class ValueClass
{
    ...
    int get() const {return ival;}
};

class QWE
{
    ...
    const ABC & getABC() const { return abc; } 
};

您的代码必须始终是const-correct,否则您将始终遇到此问题。