Overloaded Assignment Operator Copy Constructor Inheritance

Copy constructor for derived class

I'm just wondering how to write the copy constructor, along with the operator =, for a derive class, properly.



So - first of all, is this a standard way of doing copy constructors / operator =? I know these are very simple classes, but if i can understand these properly, then i can understand more complex ones.

In the derived copy constructor, i have called the base copy constructor - so should this then set the base member variables correctly? Or should i set everything in the derived operator =?

I want to make sure everything is copied correctly, but i also want to understand that what i've done is correct. Of course i could simply set all the base memeber variables in the derived operator =....... that way i'd be sure.
You haven't defined a copy-constructor (you think you have, but you haven't) so the compiler will make its own. In actual fact, the only constructor you've overloaded is the default one.

To properly overload the copy-constructor, the parameter list must have only 1 parameter, and that's a reference to a constant class . For instance:


When dealing with inheritance, be sure to invoke the base-copy-constructor, because otherwise, the base will not be affected. Though, it seems you've already done this.

Secondly, you've not overloaded the assignment operator properly, either. Again, the compiler will provide its own assignment operator. Like the copy-constructor, at least 1 overload of the assignment operator must take a reference to a constant class .

Wazzak
It is better when the copy constructor (and the copy assignment operator) accepts a constant reference to an object of its class.

Consider your declaration



and the following code



In the both cases of declarations of b2 and b3 a compilation error will be issued (provided that the compiler does not have a bug:) ).
In the first case when b2 is defined your copy constructor may not be called because object b1 is const and only a const reference can be specified for it.
In the second case the call Base() creates a temporary unnamed object. Such an object also may be binded only with a const reference.

The same remarks are valid for the copy assignment operator that is it shall have as the parameter a const reference to an object of its class.

And you do not need call the base copy constructor as you are doing

Derived::Derived(Derived &other)
:Base(other) // <---- do we do it like this?


It will be called implicitly by the derived copy constructor.

@Framework (2487)

You haven't defined a copy-constructor (you think you have, but you haven't) so the compiler will make its own. In actual fact, the only constructor you've overloaded is the default one.



You are wrong. This

// copy constructor
Base::Base(Base &other)
{
*this = other;
}


is a copy constructor. The compiler will not create its own copy constructor.
It's not a copy-constructor, but if you want to provide false information, I won't allow you. The compiler will generate its own copy-constructor, but only if it's required.

Wazzak
@Framework (2489)

It's not a copy-constructor, but if you want to provide false information, I won't allow you. The compiler will generate its own copy-constructor, but only if it's required.


I already gave your a good advice: read the C++ standard! It is very useful!
That you will understand that you are wrong consider the example I already showed here.



As you affirm in this case the compiler will create a copy constructor will not it? However if you run this code provided that you have the constructor



the compiler will issue an error because none copy constructor it did create. It already have the user defined copy constructor.
Fine, go ahead and post false information - I'm sick of arguing with you.

Wazzak
Till now it is you who give the false information. Did you try the example I showed? And where is your copy constructor created by the compiler?! Why the compiler does issue an error?
I did not get your answer except only your emotions which based on your lack of knowledge of the C++ standard.

Any constructor which has as the parameter a reference to an object of its type, a const reference to an object of its type, a volatile reference to an object of its type or a const volatile reference to an object of its type all these are copy constructors. If at least one copy constructor is declared by the user when the compiler will not generate its own copy constructor. The user can declare all four kinds of the copy constructor.

Even the following declaration



is a copy constructor.
I'm afraid vlad is correct about it being a copy-constructor.
§12.8/2
A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&, volatile X& or const volatile X&, and either there are no other parameters or else all other parameters have default arguments (8.3.6). [ Example: X::X(const X&) and X::X(X&,int=1) are copy constructors.


vlad from moscow wrote:
you do not need call the base copy constructor as you are doing
It will be called implicitly by the derived copy constructor.

This is not correct though. GCC even generates a warning if I try to remove :
warning: base class 'class Base' should be explicitly initialized in the copy constructor [-Wextra]


In Derived::operator= the variables in Base is currently not set. You can call Base::operator= from Derived::operator= to set them
@Peter87
This is not correct though. GCC even generates a warning if I try to remove :Base(other):


warning: base class 'class Base' should be explicitly initialized in the copy constructor [-Wextra]


Now you are wrong. Objects are created by first implicitly calling a base copy consttructor and only then by calling the most derived copy constructor.
Do not trust the compiler. All compilers contain bugs!:)

I think that maybe the warning message was generated by the copy assignment operator that is used inside the body of the copy constructor. So do not be hurry.:) But in any case there is no problem that the base copy constructor was not specified in the mem initializing list. I is not required.
vlad, do you even know why the copy-constructor requires a constant reference? It's because of the following:

- It allows constant class objects to be passed
- It allows temporary objects to be passed
- It guarantees referent protection

By omitting from the copy-constructor declaration, the following code is erroneous:


You cannot pass constant objects, and you cannot bind temporaries to the parameter. This is the same for the assignment operator. By default, the compiler will generate a copy-constructor that takes a reference to a constant class ; just like the assignment operator. Why? Because it's the better declaration.

vlad from moscow wrote:
"Do not trust the compiler."

Now who's wrong.

By the way, I know what a valid copy-constructor looks like; I was suggesting the best one.

Wazzak
@Framework
vlad, do you even know why the copy-constructor requires a constant reference? It's because of the following:

- It allows constant class objects to be passed
- It allows temporary objects to be passed
- It guarantees referent protection



I do not understand why are you writing this because 1) we were talking about what is a copy constructor 2) in my first message I pointed out that it is better to declare the copy constructor with a const reference and demonstrated this with examples.
So you are arguing with yourself.:) Maybe it is very useful business to argue with yourself?

@Framework
You cannot pass temporaries, you cannot pass constant objects, and you cannot bind temporaries to the parameter.


And I do not understand why are you repeating these after me?!!! See again my first message and reread your messages where you stated 1) that the compiler generates its own copy constructor in spite of presence of a user copy constructor 2) that I give a false information.
I am sorry but it seems that you are dishonest man.


Shall I repeat your statements as for example

@Framework
It's not a copy-constructor, but if you want to provide false information, I won't allow you. The compiler will generate its own copy-constructor, but only if it's required.


or you will understand at last that you was wrong?



Let's review your first post:

1)

vlad from moscow wrote:
vlad from moscow wrote:
"In the second case the call Base() creates a temporary unnamed object."

This isn't an error, nor does it create a temporary object; it's a function prototype.

2)

vlad from moscow wrote:

"It will be called implicitly by the derived copy constructor."

This is false; The compiler will not implicitly invoke the copy-constructor of the base-class, because the copy-constructor of the base class requires an argument.

vlad from moscow wrote:
"or you will understand at last that you was wrong? "

I was 100% right about what I said about the constructor being defined only if it's needed; I was not wrong. I'll explain it again, just for you: A compiler will only generate a copy-assignment operator, copy-constructor, and destructor only if they are not overloaded, and only if they are required.

Wazzak
Wow, that was a heated argument..

Anyway, back to the original post, the problem it has is that the copy constructor (which should be taking ref to const, to be more useful), is defined in terms of the copy assignment operator. It should have been written this way:



Also, the derived operator= forgets to copy the inherited members a and b.

Of course, all this could simply be omitted, since the implicitly-defined copy ctor and assignment would do the right thing in this case.
Framework wrote:
it's a function prototype
¿? No, it is not.
It is an object definition.

Framework wrote:
The compiler will not implicitly invoke the copy-constructor of the base-class, because the copy-constructor of the base class requires an argument.
That.
If you put nothing, then the default constructor will be called.

Just to state it:
is a copy constructor, but you should prefer
ne555 wrote:
"It is an object definition."

Compile this:



ne555 wrote:
"If you put nothing, then the default constructor will be called."

That's the problem; you want the base class' copy-constructor to be called when you invoke the copy-constructor of the derived class. If you don't, the base members will be initialised to default values, and will not be initialised based on the state of the referent's base-class.

Wazzak
Interesting... I was expecting an asterisk somewhere.
ne555 wrote:
"Interesting... I was expecting an asterisk somewhere."

This:


...is equivalent to:


Wazzak

@Framework

Let's review your first post:

1)

vlad from moscow wrote:

Base b2( Base() ); // compilation error

vlad from moscow wrote:

"In the second case the call Base() creates a temporary unnamed object."

This isn't an error, nor does it create a temporary object; it's a function prototype.



You do not know 1) what is the copy constructor;
you do niot know 2) when the compiler declares implicitly the copy constructor;
you do not know 3) what is the copy assignment operator;
you do not know 4) when the compiler declares implicitly the copy assignment operator;
you do not know 5) that standard class std::auto_ptr uses the copy constructor and the copy assignment operator which use as the parameter non-const reference to an object of its type;


And these are not only my words. You demonstrated these yourself.

If I made an error somewhere then I am ready to admit it. But I never say when I do not know something that my opponent are saying false and I never start tell llies. The same I can not say about you.

@ne555
Framework wrote:

Base b2( Base() ); it's a function prototype

¿? No, it is not.
It is an object definition.



It is not a problem. We very often forgot that the constructor is not a function. It is a special syntax and Base() is a type-id. This is in fact a typo. It is enough to substitute the constructor for any function that returns an object by value. For example


and to write



Topic archived. No new replies allowed.

The latest version of this topic can be found at Copy Constructors and Copy Assignment Operators (C++).

NOTE]

Starting in C++11, two kinds of assignment are supported in the language: copy assignment and move assignment. In this article "assignment" means copy assignment unless explicitly stated otherwise. For information about move assignment, see Move Constructors and Move Assignment Operators (C++).

Both the assignment operation and the initialization operation cause objects to be copied.

  • Assignment: When one object's value is assigned to another object, the first object is copied to the second object. Therefore,

    causes the value of to be copied to .

  • Initialization: Initialization occurs when a new object is declared, when arguments are passed to functions by value, or when values are returned from functions by value.

You can define the semantics of "copy" for objects of class type. For example, consider this code:

The preceding code could mean "copy the contents of FILE1.DAT to FILE2.DAT" or it could mean "ignore FILE2.DAT and make a second handle to FILE1.DAT." You must attach appropriate copying semantics to each class, as follows.

  • By using the assignment operator together with a reference to the class type as the return type and the parameter that is passed by reference—for example .

  • By using the copy constructor. For more information about the copy constructor, see Rules for Declaring Constructors.

If you do not declare a copy constructor, the compiler generates a member-wise copy constructor for you. If you do not declare a copy assignment operator, the compiler generates a member-wise copy assignment operator for you. Declaring a copy constructor does not suppress the compiler-generated copy assignment operator, nor vice versa. If you implement either one, we recommend that you also implement the other one so that the meaning of the code is clear.

Member-wise assignment is covered in more detail in (NOTINBUILD) Memberwise Assignment and Initialization.

The copy constructor takes an argument of type class-name&, where class-name is the name of the class for which the constructor is defined. For example:

Make the type of the copy constructor's argument const class-name& whenever possible. This prevents the copy constructor from accidentally changing the object from which it is copying. It also enables copying from const objects.

Compiler-generated copy constructors, like user-defined copy constructors, have a single argument of type "reference to class-name." An exception is when all base classes and member classes have copy constructors declared as taking a single argument of type constclass-name&. In such a case, the compiler-generated copy constructor's argument is also const.

When the argument type to the copy constructor is not const, initialization by copying a const object generates an error. The reverse is not true: If the argument is const, you can initialize by copying an object that is not const.

Compiler-generated assignment operators follow the same pattern with regard to const. They take a single argument of type class-name& unless the assignment operators in all base and member classes take arguments of type constclass-name&. In this case, the class's generated assignment operator takes a const argument.

When virtual base classes are initialized by copy constructors, compiler-generated or user-defined, they are initialized only once: at the point when they are constructed.

The implications are similar to those of the copy constructor. When the argument type is not const, assignment from a const object generates an error. The reverse is not true: If a const value is assigned to a value that is not const, the assignment succeeds.

For more information about overloaded assignment operators, see Assignment.

Special Member Functions

TextFile a, b; a.Open( "FILE1.DAT" ); b.Open( "FILE2.DAT" ); b = a;
// spec1_copying_class_objects.cpp class Window { public: Window( const Window& ); // Declare copy constructor. // ... }; int main() { }

0 thoughts on “Overloaded Assignment Operator Copy Constructor Inheritance”

    -->

Leave a Comment

Your email address will not be published. Required fields are marked *