简体   繁体   English

如何使对象深度只读

[英]How to make an object deeply readonly

How can I make a class, which is sometimes readonly, and sometimes writable? 我如何制作一个有时是只读的,有时是可写的类? One option is with getter/setters and a flag which indicates if the object is read-only, but that is a lot of overhead. 一个选项是与getter / setters和一个标志一起使用,该标志指示对象是否为只读,但这会产生大量开销。 I also desire this readonly property to work deeply on the object, making sure that all of the objects it contains are also readonly or writeable. 我还希望此readonly属性能够在对象上深入工作,以确保其包含的所有对象也都是只读或可写的。 Here's some example code of the desired behavior which I tried but failed to achieve using const. 这是一些我想要的行为的示例代码,我尝试使用const却未能实现。

This question is quite generic, so has probably been asked before, but I wasn't able to find a good solution to this exact problem on stackoverflow. 这个问题很笼统,所以以前可能有人问过,但是我无法在stackoverflow上找到解决这个确切问题的好方法。

Example code: https://ideone.com/4cXyNF 示例代码: 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;
}

If you change your members to functions, you can create const overloads of the methods like this 如果将成员更改为函数,则可以像这样创建const重载方法

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 住在科利鲁

You can achieve this by using member functions to return the references / pointers const if the object itself is const . 如果对象本身是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_; }
};

Now neither i_ nor in().j_ is writable in case outer is const : 现在既不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!

This is a similar solution as some else already posted, but uses a slightly different approach: 这是与已经发布的其他解决方案类似的解决方案,但是使用的方法略有不同:

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM