Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
79 views
in Technique[技术] by (71.8m points)

c++ - How to "deep freeze" object like in JavaScript?

As we know, in JavaScript, we can freeze an object in runtime such that it will be immutable, furthermore, we can recursively freeze its mutable members such that it can no longer be modified from now on. Is it possible to achieve similar thing in C++?

I am aware of that this will inevitably cause an overhead and I am OK with it. My biggest problem is my class will have public members, and it looks like there is no way to stop a non-const reference owner from changing a public member directly.


EDIT: I am going to describe the design problem I am facing and suggest some solution.

We want to parse a musical sheet (in MusicXML form) into our internal hierarchical data structure, after this, our business logic will use the data structures and retrieve needed info from it. Our internal data structure needn't and shouldn't be modified after the parsing procedure. Because parsing procedure is pretty complex, we cannot make everything const and we have to modify the object after creation, so the "freezing" idea is natural here to prevent unintended modification to our DS.

Some ideas I have:

  1. Spam getters and setters in my classes, and add a freezed flag for every class. (Most straightforward, but not tidy.)
  2. Use some accessor helper classes to achieve this read only limitation.
  3. It is too complex, and it is not worthwhile to freeze the objects.
question from:https://stackoverflow.com/questions/65918770/how-to-deep-freeze-object-like-in-javascript

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The solution is to use const.

Say you have a class MusicalSheet. You can define getters and setters for whatever data you want. Make the setters const so you can't call them on a const object or reference.

class MusicalSheet
{
public:
    void setNote(size_t position, Note note);
    const Note& getNote(size_t position) const;

private:
    // Data members
};

Then you have your parsing logic and business logic, and main to tie them together:

void parseMusic(MusicalSheet &sheet, Input &input);
void businessLogic(const MusicalSheet &sheet);

int main()
{
    MusicalSheet sheet;
    Input input(...);

    parseMusic(sheet, input);
    businessLogic(sheet);
}

Your parsing function has a non const reference to the object, so it can call setNote to fill in the data. The business logic can only access getNote as it's marked const. And getNote returns a const reference, so the inner object is also not modifiable by the business logic.

The example MusicalSheet class is obviously over simplified, and can in fact be replaced with just a std::vector<Note>, using operator[] to get and set the individual notes (along with many other functions). Like MusicalSheet, with a const vector you can only access the inner objects, not modify them.

Read the documentation on the const type qualifier and const-qualified member functions

One caveat with const is pointers. Making an int* const will give you a int* const, which is a constant pointer to a non-constant int. This is also true for smart pointers.

To get around it you can do something like this:

class DataHolder
{
public:
    std::unique_ptr<Data>& getData() { return _data; }
    const Data* getData() const { return _data.get(); }

private:
    std::unique_ptr<Data> _data;
};

Now with a DataHolder you can reassign the pointer (e.g. dataHolder.getData() = std::make_unique<Data>(...);), but with a const DataHolder all you can do is access a const Data*.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...