如何使对象深入只读

时间:2016-04-26 21:52:27

标签: c++ const

我怎样才能创建一个有时只读,有时可写的课程?一个选项是使用getter / setter和一个标志来指示对象是否是只读的,但这是一个很大的开销。我还希望这个readonly属性能够深入研究对象,确保它包含的所有对象都是readonly或writeable。这是我尝试但未能使用const实现的所需行为的一些示例代码。

这个问题非常通用,所以之前可能已经提出过,但我无法在stackoverflow上找到这个确切问题的良好解决方案。

示例代码: https://ideone.com/4cXyNF

class InnerClass {
 public:
  InnerClass(int j) : j_(j) {}
  int j_;
};

class OuterClass {
 public:
  OuterClass(int i, InnerClass& c) : i_(i), reference_(c), pointer_(&c) {}
  int i_;
  InnerClass& reference_;
  InnerClass* pointer_;
};

int main() {
    InnerClass c(1);

    OuterClass readwrite(2, c);
    // Desire these 3 operations to work on the writable object
    readwrite.i_ = 3;
    readwrite.reference_.j_ = 4;
    readwrite.pointer_->j_ = 5;

    const OuterClass readonly(6, c);
    // COMPILER ERROR: error: assignment of member 'OuterClass::i_'
    // in read-only object
    // readonly.i_ = 7;
    // Desire this to be a compiler error, but it isn't
    readonly.reference_.j_ = 8;
    // Desire this to be a compiler error, but it isn't
    readonly.pointer_->j_ = 9;

    return 0;
}

3 个答案:

答案 0 :(得分:2)

如果将成员更改为函数,则可以创建此方法的常量重载

class InnerClass {
public:

  explicit
  InnerClass(int j) : j_(j) {}

  int& j() { return j_; }
  const int& j() const { return j_; } 
private:
  int j_;
};

class OuterClass {
public:

  OuterClass(int i, InnerClass& c) : i_(i), reference_(c), pointer_(&c) {}

  int& i() { return i_; }
  const int& i() const { return i_; } 

  InnerClass const& reference() const { return reference_; };
  InnerClass & reference()  { return reference_; };

  InnerClass const* pointer() const { return pointer_; };
  InnerClass * pointer() { return pointer_; };

private:
  int i_;

  InnerClass& reference_;
  InnerClass* pointer_;
};

int main() {
    InnerClass c(1);

    OuterClass readwrite(2, c);
    // Desire these 3 operations to work on the writable object
    readwrite.i() = 3;
    readwrite.reference().j() = 4;
    readwrite.pointer()->j() = 5;

    const OuterClass readonly(6, c);
    // COMPILER ERROR: error: assignment of member 'OuterClass::i_'
    // in read-only object
    readonly.i_ = 7;
    // Desire this to be a compiler error, and it is
    readonly.reference().j() = 8;
    // Desire this to be a compiler error, and it is
    readonly.pointer()->j() = 9;

    return 0;
}

<强> Live on Coliru

答案 1 :(得分:2)

如果对象本身是const,您可以通过使用成员函数返回引用/指针const来实现此目的。

class InnerClass {
 public:
  InnerClass(int j) : j_(j) {}
  int j_;
};

class OuterClass
{
  InnerClass& reference_;
public:
  OuterClass(int i, InnerClass& c) : i_(i), reference_(c) {}
  int i_;
  InnerClass & in() { return reference_; }
  InnerClass const & in() const { return reference_; }
};

如果i_in().j_outerconst都不可写:

InnerClass i{ 1 };
OuterClass write(2, i);
write.i_ = 3; // works
write.in().j_ = 3; // works
OuterClass const read(2, i);
read.i_ = 3; // error!
read.in().j_ = 3; // error!

答案 2 :(得分:1)

这是与其他已经发布的类似的解决方案,但采用了稍微不同的方法:

class InnerClass {
 public:
  InnerClass(int j) : j_(j) {}
  int j_;
};

template<bool readOnly>
class OuterClass{
 public:
  OuterClass(int i, InnerClass& c) : i_(i), reference_(c), pointer_(&c) {}
  int i_;
  typename std::conditional<readOnly,const InnerClass&, InnerClass&>::type reference_;
  typename std::conditional<readOnly,const InnerClass* const, InnerClass*>::type pointer_;
};

int main(int argc,char** args){
    InnerClass c(1);
    OuterClass<true> readonly(12,c);
    //readonly.reference_.j_ = 1;   //Error "reference_ is read only"
    //readonly.pointer_->j_ = 1;    //Error "pointer_ is read only"
    OuterClass<false> write(12,c);
    write.reference_.j_ = 1;
    write.pointer_->j_ = 1;
}