Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

Base class constructor calling

Posted on 2003-11-09
6
928 Views
Last Modified: 2008-02-01
Ah hello.

If I have the following class definitions:

class Shape
{
public:
      Shape() { cout << "Constructing Shape object" << endl; }
      Shape(int n): name(n) { cout << "Constructing Shape object with parameter" << endl;}
      ~Shape() {cout << "Destroying Shape object " << endl; }
      int name;
};


class Rectangle : public Shape
{
public:
      Rectangle() { cout << "Constructing Rectangle object" << endl; }
      Rectangle(int n): name(n) { cout << "Constructing Rectangle object with parameter" << endl; } ***
      ~Rectangle() {cout << "Destroying Rectangle object " << endl; }
};



Now, I am getting a complier error regarding the line marked ***.

'error C2614: 'Rectangle' : illegal member initialization: 'name' is not a base or member'

Yet if I change the marked line to

Rectangle(int n) { name = n; cout << "Constructing Rectangle object with parameter" << endl; }

there is no complaint.

I am confused by this behaviour.  Linked to this question is a second:

Do I always have to *explicitly* call the base class constructor in circumstances like the above ?  Say I leave the constructor for Rectangle as this:

(1) Rectangle(int n) { name = n; cout << "Constructing Rectangle object with parameter" << endl; }

Now this is clearly initialising the inherited variable, name, right ?  Or should I be saying

(2) Rectangle(int n) : Shape(n) { cout << "Constructing Rectangle object with parameter" << endl; }

I have a gut feeling that the latter is probably considered better form, and would be the *only* option if 'name' was private in the Shape class, as Rectangle would not be able to access it via name = n.  But am I right ?  Is it a better idea to initialise inherited variables via the base class constructor call(2), or do so in the derived class constructor's body (1) and hence rely on the base class object to be constructed via its own default constructor ?

I know I have asked two questions here, but they are related, hence the points on offer are 20 for each question.

Thanks a lot !

0
Comment
Question by:mrwad99
6 Comments
 
LVL 5

Accepted Solution

by:
migoEX earned 40 total points
ID: 9709917
The MSDN says:
"Only a member or base class can be in the initialization list for a class or structure."

You can think what happens if you had Shape defined as:
class Shape {
public:
Shape() : name(n) {...}
...
};

If the derived class would also try to initialize the "name" variable, the compiler would be confused - same variable can't be initialized twice.

I think the decision about which is better - (1) or (2) depends on the design, and I would say (2) or BOTH:

In case You're not sure the base class will initialize the name variable as I wand, you can write
Rectangle(int n) : Shape(n) {name = n; ...}
0
 
LVL 1

Expert Comment

by:Mustak_Shaikh
ID: 9710820
mrwad99,

Answer to first question:
If you try to debug the above code(the correct one), you will observe
that compiler after encountering
Rectangle objRectangle(9);
will go to
Rectangle(int n)
compiler will not enter into this body,but from there it goes to Base class
and execute the base class constructor completly and come to the body of Rectangle constructor and execute it. that means at initializer list of Rectangle class, the base class object has not yet created and hence you can't refer any of its member.

2nd question: I guess the  last solution in this case is correct and a better solution. it make sense to force fully call the base class' s constructor.

Regards,
0
 
LVL 6

Expert Comment

by:GaryFx
ID: 9711584
1.  You do not always have to call the base class constructor explicitly, but there are times when it's appropriate.

2.  Yes (almost), doing name = n inside the body of the Rectangle constructor is setting the value of the inherited member variable "name."   However, it is an assignment, not an initialization.  The initialization took place when the base class constructor was called, which happens before the body of the derived class constructor is executed.  

3.  I agree that in general it is better form to pass the parameter to the base class constructor.  However, since the intent of an int variable entitled "name" isn't at clear to me, it may not matter much in this case.  In many cases, it doesn't matter all that much.

Gary
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 9

Expert Comment

by:_ys_
ID: 9714045
A general design principle is to make all member variables private by default. Occassionally they may be declared as protected. This would eliminate most of the questions you have asked.

Another best practice is to use an initialisation list, rather than to initialise (/assign) variables within the constructor body itself. For built-in [fundamental] types there would be no performance hit, but for a custom class initialisation and subsequent reassignment could be costly.
0
 
LVL 7

Expert Comment

by:jconde
ID: 9719644
This is what your function Rectangle(int) should look like:

Rectangle(int n)
: Shape(n)
{
  cout << "Constructing Rectangle object with parameter" << endl;
}
0
 
LVL 19

Author Comment

by:mrwad99
ID: 9731154
I am surprised at the feedback that this question generated !

Thanks to everyone for the advice; it seems that migoEX gave advice that completely answered the stated question and was clearly first to do so.  For that reason I have accepted his answer.

Overall cheers though to everyone who participated !
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Prototype for MessageDlg in Embacadero XE 2 2 42
C++ dll will not run on machine without VS installed 10 87
computer science syllabus 3 88
I could not build boost code, 10 94
Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

808 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question