Newbie: const Member Function

Z

Zalek Bloom

Hello,
Created a simple class with following member functions:

class student
{
private:
char Name[20];
int studentID;
Curriculum Program;

public:
void setName(char fn[20]);
char* getName() ;

void setStudentID(int sID);
int getStudentID() const;

void setCurriculum(Curriculum c) ;
Curriculum getCurriculum() ;
};


void student::setName(char a[20])
{
strcpy(Name, a);
}
void student::setStudentID(int a)
{
studentID = a;
}
void student::setCurriculum(Curriculum a)
{
Program = a;
}

char* student::getName()
{
return Name;
}
int student::getStudentID() const
{
return studentID ;
}
Curriculum student::getCurriculum()
{
return Program ;
}

Curriculum is a class defined down the line.
"const" is working with getStudentID() function, but when I try add
"const" to getCurriculum() or getName() I am getting message:

C:\\MyProjects\Aug25\prog1.cpp(53) : error C2440: 'return' : cannot
convert from 'const char [20]' to 'char *'
Conversion loses qualifiers
Error executing cl.exe.

prog1.obj - 1 error(s), 0 warning(s)

Without "const" on getName() I am getting a clear compile.

Thanks,

Zalek
 
D

David White

[snip]
# include <iostream>
# include <ostream>
# include <string>

class Student
{
private:
std::string FirstName;
std::string LastName;
public:
Student( const std::string& fn, const std::string& ln )

I prefer to use 'const char *' in cases like this, because a string will be
created unnecessarily if the argument is a char array or a string literal.
In general, I try to use the simplest type possible as a function parameter.
In most cases it's not a big deal either way, but I wondered if anyone else
has thoughts on this.

[snip]

DW
 
N

Novice

|
[snip]

| > Student( const std::string& fn, const std::string& ln )
|
| I prefer to use 'const char *' in cases like this, because a string will
be
| created unnecessarily if the argument is a char array or a string literal.
| In general, I try to use the simplest type possible as a function
parameter.
| In most cases it's not a big deal either way, but I wondered if anyone
else
| has thoughts on this.
|

As the nick implies I am a novice, but I can think of one reason why you
wouldn't want to make that parameter of type const char *.

At my level of expertise there is no reason why a std::string wouldn't
suffice in any situation where I am using char arrays or string literals.
The processing overhead of calling the constructor is worth the convenience
of being able to use std::string. Also, if you code it properly you
shouldn't need to explicitly construct the std::string from the (const char
*). Therefore, there is no inconvenience or extra clutter in your code.

That said I do have a few member functions in my C++ code that take (const
char *) as an argument. But that is because I wanted to learn how
std::string works, so I wrote my own String class (with the help of many
posters on here). So typically those parameters that are of type (const
char *) belong to my String class.

Just to elaborate on my previous remark, I have code like this:

------------
SmtStringPtr string1 (new String ("testing"));
if (string1->equals ("testing")){
//whatever
}
------------

And so long as I have the following constructor
------------
String(const char * _cString){
initialize (_cString);
}
------------
I don't need to create any other equals method other than this:
------------
virtual bool equals (SmtStringPtr string_){
//test to see if it is equal
}
------------

Since the above String constructor will automatically be invoked.

[snip]

Hope this helps,
Novice

PS To the OP - check out the FAQ for alt.comp.lang.learn.c-c++ - as a
student of C++, I have consistently found more helpful and friendly
responses on alt.comp.lang.learn.c-c++ for the reason listed in the FAQ:
This newsgroup is intended for discussion related to the practice and
process of learning C and C++. The other two groups [comp.lang.c or
comp.lang.c++]are primarily intended for general discussion of the features
of those languages.

Naturally, some overlap does occur. This group does tend to be slightly more
informal, though. Most regulars on this group show great patience with many
common beginners' questions and will willingly expound on many topics of
interest or particular difficulty, referring to appropriate reference
material, either in printed or in electronic form, as necessary.

The FAQ can be found at:
http://www.snurse-l.org/acllc-c++/faq.html
 
D

David White

Novice said:
|
[snip]

| > Student( const std::string& fn, const std::string& ln )
|
| I prefer to use 'const char *' in cases like this, because a string will
be
| created unnecessarily if the argument is a char array or a string literal.
| In general, I try to use the simplest type possible as a function
parameter.
| In most cases it's not a big deal either way, but I wondered if anyone
else
| has thoughts on this.
|

As the nick implies I am a novice, but I can think of one reason why you
wouldn't want to make that parameter of type const char *.

At my level of expertise there is no reason why a std::string wouldn't
suffice in any situation where I am using char arrays or string literals.
The processing overhead of calling the constructor is worth the convenience
of being able to use std::string. Also, if you code it properly you
shouldn't need to explicitly construct the std::string from the (const char
*). Therefore, there is no inconvenience or extra clutter in your code.


That said I do have a few member functions in my C++ code that take (const
char *) as an argument. But that is because I wanted to learn how
std::string works, so I wrote my own String class (with the help of many
posters on here). So typically those parameters that are of type (const
char *) belong to my String class.

Just to elaborate on my previous remark, I have code like this:

------------
SmtStringPtr string1 (new String ("testing"));
if (string1->equals ("testing")){
//whatever
}

That's right, but in some cases there is unnecessary inefficiency, to which
I have a natural aversion. On creation, a string does a 'new', which is a
relatively costly thing to do when it's not needed.

I shouldn't have chopped off the body of the function I cited. The complete
function was:
Student( const std::string& fn, const std::string& ln )
: FirstName( fn ), LastName( ln ) {}

In this case 'const char *' would have done just as well. The down side is
that where you do pass strings, you need to call str.c_str() to get at the
C-style string.

DW
 
J

John Harrison

David White said:
Novice said:
|
[snip]

| > Student( const std::string& fn, const std::string& ln )
|
| I prefer to use 'const char *' in cases like this, because a string will
be
| created unnecessarily if the argument is a char array or a string literal.
| In general, I try to use the simplest type possible as a function
parameter.
| In most cases it's not a big deal either way, but I wondered if anyone
else
| has thoughts on this.
|

As the nick implies I am a novice, but I can think of one reason why you
wouldn't want to make that parameter of type const char *.

At my level of expertise there is no reason why a std::string wouldn't
suffice in any situation where I am using char arrays or string literals.
The processing overhead of calling the constructor is worth the convenience
of being able to use std::string. Also, if you code it properly you
shouldn't need to explicitly construct the std::string from the (const char
*). Therefore, there is no inconvenience or extra clutter in your code.


That said I do have a few member functions in my C++ code that take (const
char *) as an argument. But that is because I wanted to learn how
std::string works, so I wrote my own String class (with the help of many
posters on here). So typically those parameters that are of type (const
char *) belong to my String class.

Just to elaborate on my previous remark, I have code like this:

------------
SmtStringPtr string1 (new String ("testing"));
if (string1->equals ("testing")){
//whatever
}

That's right, but in some cases there is unnecessary inefficiency, to which
I have a natural aversion. On creation, a string does a 'new', which is a
relatively costly thing to do when it's not needed.

I shouldn't have chopped off the body of the function I cited. The complete
function was:
Student( const std::string& fn, const std::string& ln )
: FirstName( fn ), LastName( ln ) {}

In this case 'const char *' would have done just as well. The down side is
that where you do pass strings, you need to call str.c_str() to get at the
C-style string.

DW

You creating a string anyway because FirstName and LastName are strings,
even if fn and ln are const char*. All that changes is the point at which
you create the std::string and possibly the addition of a string copy.

In fact your situation is less efficient when passing a std::string. In this
case, as you said, you use c_str() to get the unlying C string and then
create another std::string from that. In effect you've done a deep copy.
Whereas using a std::string as the parameter will probably be doing a
shallow copy, although this depends on the implementation of std::string.

Of course there's nothing to stop you overloading the constructor and
providing both (four possibilities in this case) but this get very tedious
after a while.

john
 
D

David White

John Harrison said:
You creating a string anyway because FirstName and LastName are strings,
even if fn and ln are const char*. All that changes is the point at which
you create the std::string and possibly the addition of a string copy.

If passing a string literal, I thought I'd be creating four std::strings
with const std::string & parameters, but only two (the two members) with
const char * parameters. However, if the std::strings are reference-counted,
then the cost is a lot less.
In fact your situation is less efficient when passing a std::string. In
this case, as you said, you use c_str() to get the unlying C string and
then create another std::string from that.

Why another? You are passing the c_str() of two std::strings - strings that
you already have anyway - to the constructor, which constructs the two
std::string members - which you also already have anyway - out of those
C-style strings. It's only less efficient if the std::strings have to do
another allocation when c_str() is called. I'd always imagined that the
underlying std::string is implemented as a C-style string, so that the same
buffer can serve for c_str(), data() and all the other members.
In effect you've done a deep
copy. Whereas using a std::string as the parameter will probably be doing
a shallow copy, although this depends on the implementation of
std::string.

Yes, I suppose you mean reference-counting.
Of course there's nothing to stop you overloading the constructor and
providing both (four possibilities in this case) but this get very tedious
after a while.

I agree.

DW
 
D

David White

Oh, I see what you mean. In my case we are going std::string --> const char
* --> std:: string, guaranteeing two copies of the string buffer, which is
not necessarily (and most likely isn't) the case when going std::string -->
const std::string & --> std::string.

DW
 
?

=?iso-8859-1?Q?Andr=E9_P=F6nitz?=

In alt.comp.lang.learn.c-c++ David White said:
[snip]
# include <iostream>
# include <ostream>
# include <string>

class Student
{
private:
std::string FirstName;
std::string LastName;
public:
Student( const std::string& fn, const std::string& ln )

I prefer to use 'const char *' in cases like this, because a string will be
created unnecessarily if the argument is a char array or a string literal.
In general, I try to use the simplest type possible as a function parameter.
In most cases it's not a big deal either way, but I wondered if anyone else
has thoughts on this.

Depends.

If the whole project is 'std::stringified', using .c_str() in the
caller looks not only unestheticly, but has also bad performance with
COW strings.

If it is 'glue code' to C style stuff, const char * is fine with me.

Andre'
 
C

Chris \( Val \)

| |
| [snip]
|
| > # include <iostream>
| > # include <ostream>
| > # include <string>
| >
| > class Student
| > {
| > private:
| > std::string FirstName;
| > std::string LastName;
| > public:
| > Student( const std::string& fn, const std::string& ln )
|
| I prefer to use 'const char *' in cases like this, because a string will be
| created unnecessarily if the argument is a char array or a string literal.
| In general, I try to use the simplest type possible as a function parameter.
| In most cases it's not a big deal either way, but I wondered if anyone else
| has thoughts on this.

I always prefer to use 'std::string' where I can.

If I had used 'const char*', then I would have to do:

std::string FN( "Fred" );
std::string LN( "Flinstone" );
Student Person1( FN.c_str(), LN.c_str() );

.... if I wanted to use 'std::string' as the arguments
to the constructor, where as with 'std::string', there
are enough overloads to accommodate for the arguments.

Cheers.
Chris Val
 
R

Rolf Magnus

David said:
#include <string>

class A
{
std::string m_s;
public:
A(const std::string &s) : m_s(s) {}
};

void f()
{
A a("abc");
}

For the above, an examination of the code generated by VC++ 6.0,
optimized for speed, showed the creation of a temporary std::string,
then a call to the std::string copy constructor to initialize the m_s
member, then a call to the std::string destructor to destroy the
temporary.

g++ 3.3 does the same.
 

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

Forum statistics

Threads
474,142
Messages
2,570,817
Members
47,363
Latest member
eitamoro

Latest Threads

Top