Lets have a class (called Class with capital C)
have a class member data.
But when we declare the class data in the body of the Class,
we have to initialize it with something
(default constructor or other constructor)
however in c++ the initialization used to task to the Class constructor.
But we have to initialze during the declaration before calling the constructor of the main Class.
Practically this means that you have to initialize with some stuffing values before the constructor initialiye it with the right values.
This is not a beauty as far as I understand.
It is possible to do another way?

For example the following code does not work

class mytype
{
public:
  double x;
  mytype(double x1) : x(x1) {}
};

class myclass
{
  mytype y;
public:
  myclass(double z) {}  
};

The reason is

mytype y;

declaration in the myclass which wants to call mytype() constructor which is not exist.

We have to declare somehow a member data, if this member data is a class, we have to call a constructor.

The solution is call mytype(double) constructor with some fake data (non used, non interested data, which will be overwrite when call the myclass constructor is called)

Second solution is define mytype() constructor, but what if we dont want?

The first solution is not a c++ concept I think because c++ concept is initialize with the constructor!

More solution???

The whole point of a constructor is to initialise any member variables in your class.
If members are not initialised correctly at construction, then you are at risk of inroducing all manner of bugs into your program.

So in your example, your default constructor for your mytype class should at least provide a default value for it's x member variable.

Take a look at this:

class mytype
{
public:
	double x;

	// provide a default initial value for x
	// in the default constructor
	mytype(): x(0.0){};
	mytype(double x1): x(x1){};

}

class myclass
{
public:
	mytype y;
	myclass(){};
	myclass(double z): y(z){};
}

NOTE: for the sake of brevity in this example I've made the member variables of both classes public, to save from having to create public get/set functions.

Now if you create an instance of your myclass class using the default constructor:
The default myclass constructor will use mytype's default constructor to construct its mytype member variable y.
Because the default constructor for mytype assigns a value of 0.0 to its member variable x, your myclass instance is fully initialised.

So in your main:

myclass mine;
cout << mine.y.x ; // should output 0.0

Likewise, if you use the overridden constructor which takes a double as a parameter, then your overridden constructor calls mytype's overridden constructor to construct it's y member variable.
So in main you could do this:

myclass mine(4.35);
cout << mine.y.x; // should output 4.35

Cheers for now,
Jas.

Edited 7 Years Ago by JasonHippy: n/a

Yes, but this is like my firs solution, you have to initialize with a fake parameter (in your example 0.0), this is an ugly solution.

My other question: I know your example works, but how it is possible to call two constructor for the same object? When we create a class myclass, than mytype y; declarated first with mytype() constructor, or the myclass constructor call first the y(z) constructor?

Well, for starters, it's not an ugly solution at all!
It's common sense and good practice! When constructing an object all members should correctly initialised. If you don't know what the value of a member variable is going to be when the class is instantiated, give it a default value. That way it is at least initialised!! Imagine if one of your uninitialised members was a pointer, what would happen if another part of your program attempted to use that uninitialised pointer? C R A S H !!

OK, so you give default values and you add some public functions to allow those members to be updated as and when the correct values are known.

Here, take a look at this slightly expanded example which implements what I've discussed above:

#include<iostream>
#include<string>
using namespace std;

class mytype
{
private:
	double x;

public:
	// provide a default initial value for x
	// in the default constructor
	mytype(): x(0.0){};
	mytype(double x1): x(x1){};

	double getx()const{return x;}
	void setx(double val){x=val;}
};

class myclass
{
private:
	mytype y;
public:
	myclass(){};
	myclass(double z): y(z){};

	// getter and setter to get/set myclass.y's x variable.
	double getYsX()const{return y.getx();}
	void setYsX(double val){y.setx(val);}
};

int main()
{
	// call the default constructor
	myclass mine;
	cout << "value in mine.y.x is:" << mine.getYsX() << endl;

	// now let's imagine that we've calculated a value and we want to store it in
	// x in the y of myclass instance mine
	double value = 987.3453;
	mine.setYsX(value);

	cout << "Value in mine.y.x is:" << mine.getYsX() << endl;

	// call the overridden constructor.
	myclass mine2(4.35);
	cout << "value in mine2.y.x is:" << mine2.getYsX() << endl;

	string dummy;
	cout << endl << "Press return to continue..." << endl;
	getline(cin, dummy);
	return 0;
}

With regard to the constructors, only one myclass constructor is used to construct the myclass object. But when myclass constructs it's mytype object y, then the appropriate mytype constructor is called to create the mytype object inside the myclass object...If you follow me?
Sorry if any of that confused you!

Cheers for now,
Jas.

Thanks your answer,
but I still confused about the mytype constructor in the example.

What is the timeline for the compiler?
If i create an object myclass myobj(...)
the first is the myclass constructor call,
or the myclass data member declaration?

If the declaration comes first,
than mytype is constructed with mytype() constructor
and after that in the myclass constructor
mytype is constructed once again with mytype(double) constructor.

If data member declaration is just a syntax
then why is a problem for a compiler?

Builtin types like double, has a default constructor double()?
Maybe yes, but dont initialize the double to 0.0.
Its value becomes random.
Therefore your comment about C R A S H !! and
"It's common sense and good practice!"
is not valid for the c++ builtin types, is it?

Compiler can automatically find out that the template parameter is int or long in the following example:

#include <iostream>
using namespace std;

template <class T>
T GetMax (T a, T b) {
  return (a>b?a:b);
}

int main () {
  int i=5, j=6, k;
  long l=10, m=5, n;
  k=GetMax(i,j);
  n=GetMax(l,m);
  cout << k << endl;
  cout << n << endl;
  return 0;
}

It is not necessary to write GetMax<int> or GetMax<long> if both parametrs has the same type.

The above example is a function, but what about classes?
I find that the same example with a class not works,
compiler can not automatically find out what is the template parameter:

template <typename Real>
class myclass
{
  Real x;
public:
  myclass(Real x) {}
};

int main ()
{
  myclass obj(float(0.5));
  return 0;
}

error: Missing template arguments

Why? Why is not an evidence that Real must be float in this case?

>What is the timeline for the compiler?
>If i create an object myclass myobj(...)
>the first is the myclass constructor call,
>or the myclass data member declaration?

The constructor is a magic function. You can think of it like this:

class foo {
  int x;
public:
  foo()
  {
    x = 0;
  }
};

The compiler takes the default constructor and sprinkles fairy dust on it to create something like this:

foo::foo(foo *this)
{
  // Call base class constructors
  // Call data member constructors
  // Set up virtual table
  
  this->x = 0;
}

So the timeline is that it's all done by the constructor (more or less), but most of the guts are hidden from you by the compiler. However, your explicit code in the constructor body runs last.

>Builtin types like double, has a default constructor double()?
Yes. It might not actually be a constructor though. The syntax is designed to keep things regular.

>Maybe yes, but dont initialize the double to 0.0.
>Its value becomes random.

T() (where T is a built-in type) will create an rvalue of type T with a zero value for that type. So yes, double() is required to produce an rvalue with a value equivalent to defining an object of double with static linkage (ie. it must be zero initialized):

#include <iostream>

double x;

int main()
{
  double y = double();

  // Prints the same value for x and y
  std::cout<< std::fixed << x <<'\n'<< y <<'\n';
}

>I find that the same example with a class not works,
>compiler can not automatically find out what is the template parameter:

Correct. Type deduction only works for template functions, not template classes. That's because there's not really any reasonable way to deduce the type of the class that isn't ridiculously complicated. Function parameter deduction is relatively straightforward, and it takes about 15 pages to describe all of the rules, cases, and counter-cases in the standard.

>I find that the same example with a class not works,
>compiler can not automatically find out what is the template parameter:
Correct. Type deduction only works for template functions, not template classes. That's because there's not really any reasonable way to deduce the type of the class that isn't ridiculously complicated. Function parameter deduction is relatively straightforward, and it takes about 15 pages to describe all of the rules, cases, and counter-cases in the standard.

I am very sad about that!
If I have classes with user defined member classes,
i have to write the constructor like this:

myclass1<myclass2<mystruct> > myobj(...);

and could be longer:

myclass1<myclass2<myclass3<mystruct> > > myobj(...);

and I have to put spaces between > >

Edited 6 Years Ago by merse: n/a

>i have to write the constructor like this
Yup. On the plus side, this restriction can encourage moderation in template use. ;)

>and I have to put spaces between > >
Yea, that's a wart in the syntax that should be fixed in the next revision of the standard (the so called "glorious hack" we've been promised since templates came out).

This article has been dead for over six months. Start a new discussion instead.