Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constant class members, assignment operator and QList

Please conform if I am correct and tell me whether there is a better solution:

I understand that objects with constant members like int const width; can not be handled by the synthetic assignment operator that is implicitly created by the compiler. But QList (and I suppose std::list, too) needs a working assignment operator. So when I want to use objects with constant members and QList I have three possibilities:

  1. Don't use constant members. (Not a solution)
  2. Implement my own assignment operator.
  3. Use some other container that does not need assignment operators

Is that correct? Are there other elegant solutions?

Also I wonder whether I can:

  • (4) Force the compiler to create a assignment operator that deals with constant members! (I don't understand why this is such a big problem. Why is the operator not intelligent enough to use initialization lists internally? Or am I missing something?)
  • (5) Tell QList that I will never use assignment operations in the list.

EDIT: I never assign objects of this class myself. They are only created by the copy constructor or by an overloaded constructor. So the assignment operator is only required by the container not by myself.

EDIT2: This is the assignment operator I created. I am not sure if its correct though. Cell has a two parameter constructor. These parameters set the two constant members with initialization lists. But the object also contains other variable (non const) members.

Cell& Cell::operator=(Cell const& other)
{
 if (this != &other) {
  Cell* newCell = new Cell(other.column(), other.row());
  return *newCell;
 }
 return *this;
}

EDIT3: I found this thread with almost the same question: C++: STL troubles with const class members All answers combined together answered my questions.

like image 822
problemofficer Avatar asked Nov 26 '10 19:11

problemofficer


2 Answers

You are probably a newcomer to C++ and expect it to behave like Python, Java or C#.

It is quite common to put immutable Java objects into collections. This works because in Java, you do not really put Java objects into collections but merely Java references which refer to Java objects. To be even more precise, a collection internally consists of Java reference variables, and assigning to these Java reference variables does not affect the referenced Java objects at all. They don't even notice.

I deliberately said "Java object", "Java reference" and "Java variable", because the terms "object", "reference" and "variable" have completely different meanings in C++. If you want mutable T variables, you want mutable T objects, because variables and objects are basically the same thing in C++:

A variable is introduced by the declaration of an object. The variable's name denotes the object.

In C++, variables do not contain objects -- they are objects. Assigning to a variable means changing the object (by calling the member function operator=). There is no way around it. If you have an immutable object, then the assignment a = b cannot possibly work without explicitly undermining the type system, and if you do that, then you have effectively lied to your clients about the object being immutable. Making a promise and then deliberately breaking it is rather pointless, isn't it?

Of course you could simply simulate the Java way: use a collection of pointers to immutable objects. Whether or not this is an effective solution depends on what your objects really represent. But just because this works well in Java does not mean it works well in C++. There is no such thing as an immutable value object pattern in C++. It is a good idea in Java and a terrible idea in C++.

By the way, your assignment operator is completely non-idiomatic and leaks memory. If you are serious about learning C++, you should read one of these books.

like image 102
fredoverflow Avatar answered Sep 29 '22 07:09

fredoverflow


(4) is not an option. The implicitly declared copy assignment operator assigns each member of the right-hand side object to the same member of the left-hand side object.

The compiler can't implicitly generate a copy assignment operator for a class that has const-qualified data members for the same reason that this is invalid:

const int i = 1;
i = 2;

(2) is problematic since you have to overcome this same issue somehow.

(1) is the obvious solution; if your class type has const-qualified data members, it is not assignable and assignment doesn't make much sense. Why do you say that this is not a solution?


If you don't want your class type to be assignable then you can't use it in a container that requires that its value type is assignable. All of the C++ standard library containers have this requirement.

like image 23
James McNellis Avatar answered Sep 29 '22 07:09

James McNellis