explicit call to copy constructor and operator = needed

T

trying_to_learn

Why do we need to explicitly call the copy constructor and the operator
= , for base class and member objects in composition?
....book says "You must explicitly call the GameBoard copy-constructor or
the default constructor is automatically called instead"
Why cant the compiler do this on its own. if we are making an object
through copr construction for an inherited class , then why not simply
call the corresponding copy constructors for base class objects or
composed objects ?

class GameBoard {
public:
GameBoard() { cout << "GameBoard()\n"; }
GameBoard(const GameBoard&) {
cout << "GameBoard(const GameBoard&)\n";
}
GameBoard& operator=(const GameBoard&) {
cout << "GameBoard::eek:perator=()\n";
return *this;
}
~GameBoard() { cout << "~GameBoard()\n"; }
};

class Game {
GameBoard gb; // Composition
public:
// Default GameBoard constructor called:
Game() { cout << "Game()\n"; }
// You must explicitly call the GameBoard
// copy-constructor or the default constructor
// is automatically called instead:
Game(const Game& g) : gb(g.gb) {
cout << "Game(const Game&)\n";
}
 
V

Victor Bazarov

trying_to_learn said:
Why do we need to explicitly call the copy constructor and the operator =
, for base class and member objects in composition?
What?

...book says "You must explicitly call the GameBoard copy-constructor or
the default constructor is automatically called instead"

What book is that? There is no way to "explicitly call" any c-tor.

The example below concerns _initialisation_, not an "explicit call"
to a copy constructor.
Why cant the compiler do this on its own. if we are making an object
through copr construction for an inherited class , then why not simply
call the corresponding copy constructors for base class objects or
composed objects ?

It usually does, if you let the compiler create that copy constructor
for you (what is known as "compiler-generated copy constructor"). But
if you take the reins, you have to accept _all_ responsibility. You
shouldn't expect to tell the compiler, "Wait, I'll do it", and then
still have it mop up after you.
class GameBoard {
public:
GameBoard() { cout << "GameBoard()\n"; }
GameBoard(const GameBoard&) {
cout << "GameBoard(const GameBoard&)\n";
}
GameBoard& operator=(const GameBoard&) {
cout << "GameBoard::eek:perator=()\n";
return *this;
}
~GameBoard() { cout << "~GameBoard()\n"; }
};

class Game {
GameBoard gb; // Composition
public:
// Default GameBoard constructor called:
Game() { cout << "Game()\n"; }
// You must explicitly call the GameBoard
// copy-constructor or the default constructor
// is automatically called instead:
Game(const Game& g) : gb(g.gb) {
cout << "Game(const Game&)\n";
}

}; // was missing

The point here is that if you don't specify the _initialisation_
for the "gb" member in the copy c-tor's initialiser list, the
compiler cannot _guess_ how you wanted to initialise that member,
and will invoke the _default_ constructor for it.

If you _need_ to implement the copy c-tor for whatever reason,
make sure you properly initialise all the base classes and members
(whatever "properly" means in your case).

V
 
J

John Harrison

trying_to_learn said:
Why do we need to explicitly call the copy constructor and the operator =
, for base class and member objects in composition?
...book says "You must explicitly call the GameBoard copy-constructor or
the default constructor is automatically called instead"

The context is important, the above is true *if* you are defining the copy
constructor yourself. If you are not defining the copy constructor yourself
then the default copy constructor will do this for you. Ditto assignment
operator.
Why cant the compiler do this on its own. if we are making an object
through copr construction for an inherited class , then why not simply
call the corresponding copy constructors for base class objects or
composed objects ?

I guess because BS thought that either you write the copy ctor yourself,
then your have full control but must specify everything yourself, or you use
the default copy contructor, when you have no control but needn't specify
anything. Half and half doesn't really cut it, and I guess there is going to
be the odd occasion when you don't want the base class copy ctor to be
called (suppose the base class didn't have a copy ctor).

john
 
T

trying_to_learn

trying_to_learn said:
Why do we need to explicitly call the copy constructor and the operator
= , for base class and member objects in composition?
...book says "You must explicitly call the GameBoard copy-constructor or
the default constructor is automatically called instead"
Why cant the compiler do this on its own. if we are making an object
through copr construction for an inherited class , then why not simply
call the corresponding copy constructors for base class objects or
composed objects ?

class GameBoard {
public:
GameBoard() { cout << "GameBoard()\n"; }
GameBoard(const GameBoard&) {
cout << "GameBoard(const GameBoard&)\n";
}
GameBoard& operator=(const GameBoard&) {
cout << "GameBoard::eek:perator=()\n";
return *this;
}
~GameBoard() { cout << "~GameBoard()\n"; }
};

class Game {
GameBoard gb; // Composition
public:
// Default GameBoard constructor called:
Game() { cout << "Game()\n"; }
// You must explicitly call the GameBoard
// copy-constructor or the default constructor
// is automatically called instead:
Game(const Game& g) : gb(g.gb) {
cout << "Game(const Game&)\n";
}
I probably didnt ask my question correctly. I am quoting a paragraph
from the author : Thinking in C++
"If you look more closely at Game, you’ll see that the copyconstructor
and assignment operators have explicit calls to the
member object copy-constructor and assignment operator. You will
normally want to do this because otherwise, in the case of the
copyconstructor,
the default member object constructor will be used
instead, and in the case of the assignment operator, no assignment
at all will be done for the member objects!"

My question : If I dont call copysonstructor of member objects in the
copy constructor of class Games...then the compiler will call the
default constructor for the member objects...Well if the compiler HAS to
call something ..then why not call the member copy constructors and NOT
their default constructors. if copy constructor for class game is being
called then it only makes sense that compiler chooses copy contructor of
member objects. I might be sounding dumb here but pls be patient..just
trying to get a hang of this :)
 
T

trying_to_learn

Victor said:
What book is that? There is no way to "explicitly call" any c-tor.

The example below concerns _initialisation_, not an "explicit call"
to a copy constructor.




It usually does, if you let the compiler create that copy constructor
for you (what is known as "compiler-generated copy constructor"). But
if you take the reins, you have to accept _all_ responsibility. You
shouldn't expect to tell the compiler, "Wait, I'll do it", and then
still have it mop up after you.




}; // was missing

The point here is that if you don't specify the _initialisation_
for the "gb" member in the copy c-tor's initialiser list, the
compiler cannot _guess_ how you wanted to initialise that member,
and will invoke the _default_ constructor for it.

If you _need_ to implement the copy c-tor for whatever reason,
make sure you properly initialise all the base classes and members
(whatever "properly" means in your case).

V
Thanks for ure reply Victor ...U said Quote " The point here is that if
you don't specify the _initialisation_
for the "gb" member in the copy c-tor's initialiser list, the
compiler cannot _guess_ how you wanted to initialise that member,
and will invoke the _default_ constructor for it" End Quote

My point is :The compile does not have to guess how to initialize the
member objrcts in this case. its obvious since the call to the game
class object was by value then all the member objects should also be
initialized by value and hence their copy constructors should be called
and not their default constructors?
 
T

Timothy Madden

Victor Bazarov said:
What book is that? There is no way to "explicitly call" any c-tor.

Oh but there is a way ....

Write something like

(*this).ClassName::ClassName("Hello", false);

From within another constructor for ClassName.
Constructors are allowed to be called from within constructors.
I used this once to initialize const and reference members with computed
values
which I could not simply provide in the base initializer list

"Timothy Madden"
Romania
 
V

Victor Bazarov

trying_to_learn said:
[...]
My point is :The compile does not have to guess how to initialize the
member objrcts in this case. its obvious since the call to the game
class object was by value then all the member objects should also be
initialized by value and hence their copy constructors should be called
and not their default constructors?

No, it's _not_ obvious. If you haven't encountered any cases where
one specifically does _not_ need copy-construction, it doesn't mean
there can be none. Once again, think about this: if by omitting the
initialiser from the initialiser list you will get copy-initialisation
(anyway), what would be the syntax to prevent it, given that I _do_
want to prevent the copy-initialisation for some reason?

The whole paradigm behind the language like C or C++ is that once you
take over, you have to take over _all_the_way_. Yes, there is default
behaviour in many cases. That's what the _default_ copy-constructor
is for. You don't care to specify the detail of constructing an object
from another object, let the compiler do _all_the_work_ by omitting the
entire constructor. But if you choose not to use the _default_, make
sure you specify everything correctly.

Well, this newsgroup is not a very good place to discuss _why_ things
are the way they are in C++. At this point there is C++ International
Standard, and the things are because they are specified as such in
the Standard. If you think you need clarification on _why_ certain
things were put in the Standard in a certain way, ask in comp.std.c++,
that's where people discuss rationales behind the Standard, and how to
make it better where possible.

V
 
V

Victor Bazarov

Timothy said:
Oh but there is a way ....

Write something like

(*this).ClassName::ClassName("Hello", false);

From within another constructor for ClassName.

What ClassName? And what's going to happen? Do I win a prize?
Constructors are allowed to be called from within constructors.

No. There can be no argument about it. Read the frigging FAQ, read
the archives, read the Standard.
I used this once to initialize const and reference members with computed
values
which I could not simply provide in the base initializer list

struct A {
int i;
A(int i) : i(i) {}
A() {
(*this).A::A(42); // what's going to happen here?
}
};

#include <iostream>
int main() {
A a(7), aa;
std::cout << a.i << aa.i << std::endl;
}

-------------------
Comeau C/C++ 4.3.3 (Aug 6 2003 15:13:37) for ONLINE_EVALUATION_BETA1
Copyright 1988-2003 Comeau Computing. All rights reserved.
MODE:strict errors C++

"ComeauTest.c", line 5: error: a constructor or destructor may not have
its address
taken
(*this).A::A(42);
^

1 error detected in the compilation of "ComeauTest.c".
-------------------

Whatever your compiler does to accept the code above is in violation
of the Standard. Throw that compiler away.

V
 
V

Victor Bazarov

trying_to_learn said:
[...]
My question : If I dont call copysonstructor of member objects in the
copy constructor of class Games...then the compiler will call the
default constructor for the member objects...Well if the compiler HAS to
call something ..then why not call the member copy constructors and NOT
their default constructors. if copy constructor for class game is being
called then it only makes sense that compiler chooses copy contructor of
member objects. I might be sounding dumb here but pls be patient..just
trying to get a hang of this :)

Why? Because the language is specified that way in the Standard document.
If you need to know why the Standard was written that way, post to
comp.std.c++. They will explain. comp.lang.c++ is about How, not Why.

V
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top