Trouble with constructor

S

San

Hi,

I wrote two simple constructors (one of them default) to initialize a
student object.
Student::Student(string name)
{
student_name = name;
student_id = LATEST_ID + 1;
student_address("");
student_phone(0);
student_email("");

}
Student::Student()
{
student_name("");
student_id = LATEST_ID + 1;
student_address("");
student_phone(0);
student_email("");
}

When I try to use the following:
Student stud_1("San");
The g++ compiler gives an error message "undefined message to
Student::Student(basic_string(char, string_char_traits(char),
_default_alloc_template(0,0)))"

The compiler has no problem if I use Student stud_1();

Is the trouble due to the fact that I am trying to assign a string and
that there is no copy constructor defined?

Any help would be greatly appreciated.

Thanks,
San
 
L

Leor Zolman

Hi,

I wrote two simple constructors (one of them default) to initialize a
student object.
Student::Student(string name)
{
student_name = name;
student_id = LATEST_ID + 1;
student_address("");
You've confused member initializer syntax with stuff you do elsewhere than
in the initializer list. You want something like this:

Student::Student(string name) : student_name(name),
student_id(LATEST_ID + 1), student_phone(0) {}

and just leave the others out (assuming their default constructor behaves
the same as their constructor taking "")

Note that the only place member objects can be /initialized/ by a
constructor is in that constructor's initializer list; otherwise, if you
leave the job until you're within the body of the constructor, you're stuck
with having to do an /assignment/ (and the objects you're assigning to will
already have had their default constructors run on them, whether you like
it or not.)
-leor
 
J

John Carson

San said:
Hi,

I wrote two simple constructors (one of them default) to initialize a
student object.
Student::Student(string name)
{
student_name = name;
student_id = LATEST_ID + 1;
student_address("");
student_phone(0);
student_email("");

}
Student::Student()
{
student_name("");
student_id = LATEST_ID + 1;
student_address("");
student_phone(0);
student_email("");
}

When I try to use the following:
Student stud_1("San");
The g++ compiler gives an error message "undefined message to
Student::Student(basic_string(char, string_char_traits(char),
_default_alloc_template(0,0)))"

The compiler has no problem if I use Student stud_1();

Is the trouble due to the fact that I am trying to assign a string and
that there is no copy constructor defined?

Any help would be greatly appreciated.

Thanks,
San

Unless g++ supports all sorts of non-standard nonsense, neither of your
constructors can compile. You can't make assignments with calls like

student_name("");

or

student_phone(0);

Show us the real code and we may have some chance of identifying the
problem.

Incidentally,

Student stud_1();

does not define a Student object and invoke the default constructor.
Rather, it
declares a function called stud_1 that takes no arguments and returns a
Student object. To define a Student object, drop the brackets, i.e., use

Student stud_1;
 
M

Mike Higginbottom

I wrote two simple constructors (one of them default) to initialize a
student object.
[snip]

When I try to use the following:
Student stud_1("San");
The g++ compiler gives an error message "undefined message to
Student::Student(basic_string(char, string_char_traits(char),
_default_alloc_template(0,0)))"

It would be nice to see the class declaration but the following works fine
on .NET:

class Student
{
public:
Student();
Student(std::string name);
private:
std::string student_name;
};

Student::Student(std::string name)
{
student_name = name;
}

Student::Student()
{
student_name = ""; //Note: this is not student_name("")
}

Student stud_1("San");
The compiler has no problem if I use Student stud_1();
I'd expect it to fail on:

student_name("");
Is the trouble due to the fact that I am trying to assign a string and
that there is no copy constructor defined?
No. The default copy ctor will work fine for this class and will just
call the copy ctor for std::string which does exist.
Any help would be greatly appreciated.
A better (more efficient) way would be to use initialization rather than
assignment (see [1] or Scott Meyers' Effective C++)in the two ctors you
define, as follows:

Student::Student(std::string name) : student_name(name)
{
}

which may have been what you were trying to do inthe first place.

[1] http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.6
 
L

Leor Zolman

Incidentally,

Student stud_1();

does not define a Student object and invoke the default constructor.
Rather, it
declares a function called stud_1 that takes no arguments and returns a
Student object. To define a Student object, drop the brackets, i.e., use

Student stud_1;

Good catch. I missed it (but I must admit I wasn't looking all that hard
any more by the time I reached that section of the post).

Ironically, this is the very item I contributed to Bruce Eckel & Chuck
Allison's "C++ Annoyances" session at SD West recently. The reason it
annoys me should now be quite apparent: I don't /notice/ it ;-)
-leor
 
M

Mike Higginbottom

Good catch. I missed it (but I must admit I wasn't looking all that hard
any more by the time I reached that section of the post).

Ironically, this is the very item I contributed to Bruce Eckel & Chuck
Allison's "C++ Annoyances" session at SD West recently. The reason it
annoys me should now be quite apparent: I don't /notice/ it ;-)
-leor

Not just me then ;)
 
G

Gary Labowitz

Mike Higginbottom said:
I wrote two simple constructors (one of them default) to initialize a
student object.
[snip]
When I try to use the following:
Student stud_1("San");
The g++ compiler gives an error message "undefined message to
Student::Student(basic_string(char, string_char_traits(char),
_default_alloc_template(0,0)))"
It would be nice to see the class declaration but the following works fine
on .NET:

class Student
{
public:
Student();
Student(std::string name);
private:
std::string student_name;

I'd like to see if OP declared student_name that way. I'm thinking it
was a c-style string.

All other problems were taken care of.
 
S

San

Here's the class definition:
//-----------------------------------------------------------------------------
#ifndef Student_h
#define Student_h

#include <string>

namespace stud{

class Student
{
private:
static const long LATEST_ID = 99999999;
string student_name;
long student_id;
string student_address;
long student_phone;
string student_email;

public:
Student();

Student(std::string name);

}; //class student
} //namespace stud

#endif

//-----------------------------------------------------------------------------

I changed the implementation or cpp file to include the foll:

#include "Student.h"
#include <string>

namespace stud{

Student::Student(std::string name)
{
student_name = name;
student_id = LATEST_ID + 1;
}

Student::Student()
{
student_name = "";
student_id = LATEST_ID + 1;
}
} //namespace stud

//-----------------------------------------------------------------------------


The main file code contains the foll:

#include "Student.h"
using namespace std;
using namespace stud;

int main()
{
Student stud_1;
Student stud_2("San");
return 0;
}



I am aware of the advantages using initialization before the
constructor body and did start out with that. But when I came across
the errors, I thought maybe I was doing something wrong in the
initialization part and so resorted to assigment in the body.

If I have to initialize a string variable with an empty string and a
long integer with 0 isnt this the right way to do it?
Student::Student():student_name(""),student_phone(0){}


Thanks for all the advice. The Student stud_1(); thing was really
silly of me :)


As an aside, I have just realised that posting to Usenet using Google
incurs a long delay. Being new to the usenet community, I am trying to
find newsreaders that update posts faster. Kindly bear with me.

Thanks,
Santosh
 
L

Leor Zolman

Hi,
Looking better. Here are some tips:
Here's the class definition:
//-----------------------------------------------------------------------------
#ifndef Student_h
#define Student_h

#include <string>

namespace stud{

class Student
{
private:
static const long LATEST_ID = 99999999;
string student_name;
long student_id;
string student_address;
long student_phone;
string student_email;

public:
Student();

Student(std::string name);

}; //class student
} //namespace stud

#endif
I changed the implementation or cpp file to include the foll:

#include "Student.h"
#include <string>

It's convention to put the standard headers /first/, and you user-defined
headers last. Not absolutely required, but A Good Idea.
namespace stud{

Student::Student(std::string name)
{
student_name = name;
student_id = LATEST_ID + 1;

Since LATEST_ID is a static const, what are you thinking here by assigning
the /same/ value to each student_id? It would make more sense if LATEST_ID
were really latest_id, non-const, initialized to whatever, and incremented
in each constructor (if you haven't dealt with the issue of initializing
static data yet, note that you must declare such data in-class and still
define and initialize it outside the class, usually in the implementation
file.)

Also, student_phone, being a long, does need to be initialized. If I
omitted it earlier in my example initialization list, it is simply because
I didn't notice it there among all the strings, and/or I figured it would
be a string. In fact, it would be better off as a string. I don't think
you'd be able to represent my full phone area code/number with a 32-bit
long ;-)
}

Student::Student()
{
student_name = "";
student_id = LATEST_ID + 1;

Same story with LATEST_ID and student_phone.
}
} //namespace stud

//-----------------------------------------------------------------------------


The main file code contains the foll:

#include "Student.h"
using namespace std;
using namespace stud;

int main()
{
Student stud_1;
Student stud_2("San");
return 0;
}



I am aware of the advantages using initialization before the
constructor body and did start out with that. But when I came across
the errors, I thought maybe I was doing something wrong in the
initialization part and so resorted to assigment in the body.

Hope my earlier explanation of that made enough sense.
If I have to initialize a string variable with an empty string and a
long integer with 0 isnt this the right way to do it?
Student::Student():student_name(""),student_phone(0){}

In /your/ case, this works, but you'd be better off allowing the string to
be default-initialized, which you can do by simply omitting the initializer
altogether.
Thanks for all the advice. The Student stud_1(); thing was really
silly of me :)

No, it wasn't. I, and most other C++ programmers (I dare say) have done it,
and perhaps still do it, on a regular basis ;-)
As an aside, I have just realised that posting to Usenet using Google
incurs a long delay. Being new to the usenet community, I am trying to
find newsreaders that update posts faster. Kindly bear with me.

Try Agent. There's Free Agent, but the full-blown version is well worth the
money.
-leor
 
J

John Harrison

It's convention to put the standard headers /first/, and you user-defined
headers last. Not absolutely required, but A Good Idea.

It might be a convention but its not a good idea. By putting "Student.h"
first the OP checks that the header does not have any unwanted include order
requirements of other header files. For instance suppose that "Student.h"
required the std::string class to be fully defined, but the OP had omitted
to #include <string> in Student.h. With your suggestion this error would not
be found.

Generally speaking when writing some_file.cpp, some_file.h should be the
first included file.

john
 
L

Leor Zolman

It might be a convention but its not a good idea. By putting "Student.h"
first the OP checks that the header does not have any unwanted include order
requirements of other header files. For instance suppose that "Student.h"
required the std::string class to be fully defined, but the OP had omitted
to #include <string> in Student.h. With your suggestion this error would not
be found.

Okay, I can see the value in that... this sent me scrambling to see how
often your convention is actually used among the "high end" C++ texts out
there. The first thing I noticed was that gathering evidence is difficult,
since books like TC++PL and _Accelerated C++_ simply don't list complete
source files in the text...so you can't really tell what the authors'
preferred inclusion order is.

However, a few of the landmark books, such as "Modern C++ Design", do have
code associated with them (Loki in the case of that particular book).
Andrei Alexandrescu /does/ indeed use your convention. That's a serious
endorsement.

I think I've just switched my convention.
Thanks,
-leor
 
S

San

Hi,
While trying to reply to this message, I started a new thread by
mistake. Sorry about that.

Here's the class definition:
//-----------------------------------------------------------------------------
#ifndef Student_h
#define Student_h

#include <string>

namespace stud{

class Student
{
private:
static const long LATEST_ID = 99999999;
string student_name;
long student_id;
string student_address;
long student_phone;
string student_email;

public:
Student();

Student(std::string name);

}; //class student
} //namespace stud

#endif

//-----------------------------------------------------------------------------

I changed the implementation or cpp file to include the foll:

#include "Student.h"
#include <string>

namespace stud{

Student::Student(std::string name)
{
student_name = name;
student_id = LATEST_ID + 1;
}

Student::Student()
{
student_name = "";
student_id = LATEST_ID + 1;
}
} //namespace stud

//-----------------------------------------------------------------------------


The main file code contains the foll:

#include "Student.h"
using namespace std;
using namespace stud;

int main()
{
Student stud_1;
Student stud_2("San");
return 0;
}



I am aware of the advantages using initialization before the
constructor body and did start out with that. But when I came across
the errors, I thought maybe I was doing something wrong in the
initialization part and so resorted to assigment in the body.

If I have to initialize a string variable with an empty string and a
long integer with 0 isnt this the right way to do it?
Student::Student():student_name(""),student_phone(0){}


Thanks for all the advice. The Student stud_1(); thing was really
silly of me :)


As an aside, I have just realised that posting to Usenet using Google
incurs a long delay. Being new to the usenet community, I am trying to
find newsreaders that update posts faster. Kindly bear with me.

Thanks,
Santosh


Gary Labowitz said:
Mike Higginbottom said:
I wrote two simple constructors (one of them default) to initialize a
student object.
[snip]
When I try to use the following:
Student stud_1("San");
The g++ compiler gives an error message "undefined message to
Student::Student(basic_string(char, string_char_traits(char),
_default_alloc_template(0,0)))"
It would be nice to see the class declaration but the following works fine
on .NET:

class Student
{
public:
Student();
Student(std::string name);
private:
std::string student_name;

I'd like to see if OP declared student_name that way. I'm thinking it
was a c-style string.

All other problems were taken care of.
 

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
474,164
Messages
2,570,898
Members
47,439
Latest member
shasuze

Latest Threads

Top