472,961 Members | 1,543 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,961 software developers and data experts.

Problem with constructor call of a string class

Hello experts,

I have the following code me.

=cat mystring.h
#include<iostream>
using namespace std;

class mystring
{
char* p;
int capacity;
int len;
enum {DEF_SIZE = 100};
public:
// Constructors
mystring();
mystring(int size);
mystring(const char* str);

// Iniializer
void init(int size = DEF_SIZE);

//Destructor
~mystring();

//Copy Constructor
mystring(mystring&);

//Assignment Operator
mystring& operator = (mystring&);

//Display String
void display();

};

=cat mystring.cpp
#include<iostream>
using namespace std;

#include "mystring.h"

//Constructors
mystring::mystring()
{
cout << "Default Constructor" << endl;
init();
len = 0;
}

mystring::mystring(int size)
{
cout << "Constructor having size" << endl;
init(size);
len = 0;
}

mystring::mystring(const char* str)
{
cout << "Constructor with string argument" << endl;
int length = strlen(str);
init(length + 1);
len = length + 1;
strcpy(p, str);
}

void mystring::init(int size)
{
p = new char[size];
capacity = size;
}

mystring::~mystring()
{
cout << "Destructor" << endl;
delete p;
p = NULL;
}
mystring::mystring(mystring& other)
{
cout << "Copy Constructor" << endl;
delete p;
p = new char[strlen(other.p) + 1];
strcpy(p,other.p);
}

mystring& mystring::operator=(mystring& other)
{
cout << "Assignment Operator" << endl;
if(this == &other)
return *this;
delete p;
p = new char[strlen(other.p)+1];
strcpy(p,other.p);
return *this;
}

void mystring::display()
{
cout << *p << endl;
cout << "Length of string is " << len << endl;
cout << "Capacity of the string is " << capacity << endl;
}

=cat str.cpp
#include<iostream>
using namespace std;
#include "mystring.h"

int main()
{
mystring s = "Nitin";
return 0;
}

Compiling this gives error.

=g++ mystring.cpp str.cpp
str.cpp: In function `int main()':
str.cpp:7: no matching function for call to
`mystring::mystring(mystring)'
mystring.h:24: candidates are: mystring::mystring(mystring&)
mystring.h:15: mystring::mystring(const char*)
mystring.h:14: mystring::mystring(int)
str.cpp:7: initializing temporary from result of
`mystring::mystring(const
char*)'

Changing the parameter of the copy constructor to "const mystring&"
solves the problem. Can someone please explain how it makes a
difference ?

Thanks in advance.

Feb 6 '07 #1
7 2643
* dragoncoder:
>
Changing the parameter of the copy constructor to "const mystring&"
solves the problem. Can someone please explain how it makes a
difference ?
A temporary (the actual argument) can't be bound to a reference to
non-const.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Feb 6 '07 #2
the form for a copy constructor uses the const key word. When you use
the = operator, it calls the copy constructor. Since you don't have a
mystring(const mystring&) constructor, the compiler doesn't really
know what your copy constructor is.

On Feb 6, 9:45 am, "dragoncoder" <pktiw...@gmail.comwrote:
Hello experts,

I have the following code me.

=cat mystring.h
#include<iostream>
using namespace std;

class mystring
{
char* p;
int capacity;
int len;
enum {DEF_SIZE = 100};
public:
// Constructors
mystring();
mystring(int size);
mystring(const char* str);

// Iniializer
void init(int size = DEF_SIZE);

//Destructor
~mystring();

//Copy Constructor
mystring(mystring&);

//Assignment Operator
mystring& operator = (mystring&);

//Display String
void display();

};

=cat mystring.cpp
#include<iostream>
using namespace std;

#include "mystring.h"

//Constructors
mystring::mystring()
{
cout << "Default Constructor" << endl;
init();
len = 0;

}

mystring::mystring(int size)
{
cout << "Constructor having size" << endl;
init(size);
len = 0;

}

mystring::mystring(const char* str)
{
cout << "Constructor with string argument" << endl;
int length = strlen(str);
init(length + 1);
len = length + 1;
strcpy(p, str);

}

void mystring::init(int size)
{
p = new char[size];
capacity = size;

}

mystring::~mystring()
{
cout << "Destructor" << endl;
delete p;
p = NULL;}

mystring::mystring(mystring& other)
{
cout << "Copy Constructor" << endl;
delete p;
p = new char[strlen(other.p) + 1];
strcpy(p,other.p);

}

mystring& mystring::operator=(mystring& other)
{
cout << "Assignment Operator" << endl;
if(this == &other)
return *this;
delete p;
p = new char[strlen(other.p)+1];
strcpy(p,other.p);
return *this;

}

void mystring::display()
{
cout << *p << endl;
cout << "Length of string is " << len << endl;
cout << "Capacity of the string is " << capacity << endl;

}

=cat str.cpp
#include<iostream>
using namespace std;
#include "mystring.h"

int main()
{
mystring s = "Nitin";
return 0;

}

Compiling this gives error.

=g++ mystring.cpp str.cpp
str.cpp: In function `int main()':
str.cpp:7: no matching function for call to
`mystring::mystring(mystring)'
mystring.h:24: candidates are: mystring::mystring(mystring&)
mystring.h:15: mystring::mystring(const char*)
mystring.h:14: mystring::mystring(int)
str.cpp:7: initializing temporary from result of
`mystring::mystring(const
char*)'

Changing the parameter of the copy constructor to "const mystring&"
solves the problem. Can someone please explain how it makes a
difference ?

Thanks in advance.


Feb 6 '07 #3
* mike:
the form for a copy constructor uses the const key word. When you use
the = operator, it calls the copy constructor. Since you don't have a
mystring(const mystring&) constructor, the compiler doesn't really
know what your copy constructor is.
First, please don't top-post in this newsgroup -- see the FAQ.

Now, there are an infinite number of possible copy constructor signatures.

However, with one formal argument there are only four, corresponding to
the four possible combinations of having or not having 'volatile' and
'const'. Of these four, two have 'const', and two don't. As an example
of a copy constructor with non-const argument, check out std::auto_ptr.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Feb 6 '07 #4
On Feb 6, 11:53 am, "Alf P. Steinbach" <a...@start.nowrote:
* dragoncoder:
Changing the parameter of the copy constructor to "const mystring&"
solves the problem. Can someone please explain how it makes a
difference ?

A temporary (the actual argument) can't be bound to a reference to
non-const.
I am sorry I still don't get it. Where is the copy constructor
involved here? I am trying to call the constructor with the "const
char*" argument. Please explain.

Feb 6 '07 #5
* dragoncoder:
On Feb 6, 11:53 am, "Alf P. Steinbach" <a...@start.nowrote:
>* dragoncoder:
>>Changing the parameter of the copy constructor to "const mystring&"
solves the problem. Can someone please explain how it makes a
difference ?
A temporary (the actual argument) can't be bound to a reference to
non-const.

I am sorry I still don't get it. Where is the copy constructor
involved here? I am trying to call the constructor with the "const
char*" argument. Please explain.
Except for possible optimization, which doesn't affect the requirements
on the string class, the statement

mystring s = "Nitin";

is equivalent to

mystring temp( "Nitin" );
mystring s( temp );

for some unique name 'temp'.

Repeat: even though just about any compiler optimizes away the
temporary, i.e. you don't get an actual copy constructor call, the copy
constructor must be available to do the job as if no optimization.

...

OK, lets go through the rest of the code, also.

=cat mystring.h
#include<iostream>
Not necessary since iostreams aren't used in the header.

using namespace std;
Never have 'using namespace std;' in a header.

class mystring
{
char* p;
int capacity;
int len;
enum {DEF_SIZE = 100};
Reserve all uppercase identifiers for macros.

public:
// Constructors
mystring();
mystring(int size);
Naming: here you probably mean capacity, not size.

mystring(const char* str);

// Iniializer
void init(int size = DEF_SIZE);
Should not be public.

//Destructor
~mystring();

//Copy Constructor
mystring(mystring&);
Needs 'const' for the argument.

//Assignment Operator
mystring& operator = (mystring&);
Needs 'const' for the argument.

//Display String
void display();
OK as a debugging aid while developing the class, but after that, will
bind use of the class to some particular i/o environment, so ungood.
>
};

=cat mystring.cpp
#include<iostream>
using namespace std;

#include "mystring.h"
It's a good idea to include the module header as the very first thing in
the implementation file (not after anything else, except comments), to
make more sure that it includes everything necessary.
//Constructors
mystring::mystring()
{
cout << "Default Constructor" << endl;
init();
len = 0;
}

mystring::mystring(int size)
{
cout << "Constructor having size" << endl;
init(size);
len = 0;
}

mystring::mystring(const char* str)
{
cout << "Constructor with string argument" << endl;
int length = strlen(str);
init(length + 1);
len = length + 1;
Although 'len' doesn't seem to be used for anything, if it's meant to
represent the length of the string then surely it should be 'length',
not 'length+1'.

strcpy(p, str);
}

void mystring::init(int size)
{
p = new char[size];
capacity = size;
}

mystring::~mystring()
{
cout << "Destructor" << endl;
delete p;
p = NULL;
Assignment of NULL unnecessary - the destructor call is the last thing
that ever happens with this object.

}
mystring::mystring(mystring& other)
{
cout << "Copy Constructor" << endl;
delete p;
p has not been initialized, so this is Undefined Behavior.

p = new char[strlen(other.p) + 1];
strcpy(p,other.p);
Fields of 'other' not copied.

}

mystring& mystring::operator=(mystring& other)
{
cout << "Assignment Operator" << endl;
if(this == &other)
return *this;
delete p;
p = new char[strlen(other.p)+1];
At this point you may get an exception. OK, it's not a practical
consideration, because when you run out of memory there's not much to do
except terminate. But as a general principle, strive to create
exception safe code -- here you'd leave the object with an invalid 'p'
member.

The 'swap' idiom for assignment helps with exception safe assignment.

strcpy(p,other.p);
return *this;
}

void mystring::display()
{
cout << *p << endl;
cout << "Length of string is " << len << endl;
cout << "Capacity of the string is " << capacity << endl;
}

=cat str.cpp
#include<iostream>
using namespace std;
#include "mystring.h"

int main()
{
mystring s = "Nitin";
return 0;
}

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Feb 6 '07 #6
On Feb 6, 3:34 pm, "Alf P. Steinbach" <a...@start.nowrote:
* dragoncoder:
On Feb 6, 11:53 am, "Alf P. Steinbach" <a...@start.nowrote:
* dragoncoder:
>Changing the parameter of the copy constructor to "const mystring&"
solves the problem. Can someone please explain how it makes a
difference ?
A temporary (the actual argument) can't be bound to a reference to
non-const.
I am sorry I still don't get it. Where is the copy constructor
involved here? I am trying to call the constructor with the "const
char*" argument. Please explain.

Except for possible optimization, which doesn't affect the requirements
on the string class, the statement

mystring s = "Nitin";

is equivalent to

mystring temp( "Nitin" );
mystring s( temp );

for some unique name 'temp'.

Repeat: even though just about any compiler optimizes away the
temporary, i.e. you don't get an actual copy constructor call, the copy
constructor must be available to do the job as if no optimization.

...

OK, lets go through the rest of the code, also.
=cat mystring.h
#include<iostream>

Not necessary since iostreams aren't used in the header.
using namespace std;

Never have 'using namespace std;' in a header.
class mystring
{
char* p;
int capacity;
int len;
enum {DEF_SIZE = 100};

Reserve all uppercase identifiers for macros.
public:
// Constructors
mystring();
mystring(int size);

Naming: here you probably mean capacity, not size.
mystring(const char* str);
// Iniializer
void init(int size = DEF_SIZE);

Should not be public.
//Destructor
~mystring();
//Copy Constructor
mystring(mystring&);

Needs 'const' for the argument.
//Assignment Operator
mystring& operator = (mystring&);

Needs 'const' for the argument.
//Display String
void display();

OK as a debugging aid while developing the class, but after that, will
bind use of the class to some particular i/o environment, so ungood.
};
=cat mystring.cpp
#include<iostream>
using namespace std;
#include "mystring.h"

It's a good idea to include the module header as the very first thing in
the implementation file (not after anything else, except comments), to
make more sure that it includes everything necessary.


//Constructors
mystring::mystring()
{
cout << "Default Constructor" << endl;
init();
len = 0;
}
mystring::mystring(int size)
{
cout << "Constructor having size" << endl;
init(size);
len = 0;
}
mystring::mystring(const char* str)
{
cout << "Constructor with string argument" << endl;
int length = strlen(str);
init(length + 1);
len = length + 1;

Although 'len' doesn't seem to be used for anything, if it's meant to
represent the length of the string then surely it should be 'length',
not 'length+1'.
strcpy(p, str);
}
void mystring::init(int size)
{
p = new char[size];
capacity = size;
}
mystring::~mystring()
{
cout << "Destructor" << endl;
delete p;
p = NULL;

Assignment of NULL unnecessary - the destructor call is the last thing
that ever happens with this object.
}
mystring::mystring(mystring& other)
{
cout << "Copy Constructor" << endl;
delete p;

p has not been initialized, so this is Undefined Behavior.
p = new char[strlen(other.p) + 1];
strcpy(p,other.p);

Fields of 'other' not copied.
}
mystring& mystring::operator=(mystring& other)
{
cout << "Assignment Operator" << endl;
if(this == &other)
return *this;
delete p;
p = new char[strlen(other.p)+1];

At this point you may get an exception. OK, it's not a practical
consideration, because when you run out of memory there's not much to do
except terminate. But as a general principle, strive to create
exception safe code -- here you'd leave the object with an invalid 'p'
member.

The 'swap' idiom for assignment helps with exception safe assignment.


strcpy(p,other.p);
return *this;
}
void mystring::display()
{
cout << *p << endl;
cout << "Length of string is " << len << endl;
cout << "Capacity of the string is " << capacity << endl;
}
=cat str.cpp
#include<iostream>
using namespace std;
#include "mystring.h"
int main()
{
mystring s = "Nitin";
return 0;
}

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?- Hide quoted text -

- Show quoted text -- Hide quoted text -

- Show quoted text -
one more thing
use delete [] p instead of delete p

Feb 6 '07 #7
mike wrote:
the form for a copy constructor uses the const key word.
Not necessarily. Any function that can take a reference
to a single argument of the type of the class is a copy constructor
regardless of the cv-qualification.

When you use
the = operator, it calls the copy constructor.
The = operator in his case does not use the copy constructor.

The = in the first line of his main function is NOT an operator.
It's the syntax for initialization.
Feb 8 '07 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Martin Jensen | last post by:
Hi I have a problem with Qt. My class definition is this: class Button : public QObject, public Tk_Object { Q_OBJECT public: Button() {} Button(Tk_Object &p); ~Button();
4
by: Gama Franco | last post by:
Hi, I've been developing this API, but now I get stuck in a compiling error and I'm out of ideas. Some comments are welcome. The hierarchy is bases in three classes, and I will explain it...
2
by: max_sang | last post by:
Hello I have a nasty problem... take a look at this code: struct Parser { Parser(const string& s) { ... tokenizes s into pieces... } template <class T> to(size_t idx); private: vector<string>...
4
by: Greg | last post by:
Is it possible to call a constructor from within a constructor I mean Class A { public A(string getModifiedVal) { .........
7
by: Sergey Poberezovskiy | last post by:
Hi, I created two base forms: frmList and frmDetail, compiled them into a dll, and then want to use in my new project. The problem: When I created new inherited form, say frmClients, I cannot...
30
by: dbuchanan | last post by:
ComboBox databindng Problem == How the ComboBox is setup and used: My comboBox is populated by a lookup table. The ValueMember is the lookup table's Id and the DisplayMember is the text from a...
9
by: esakal | last post by:
Hello, I'm programming an application based on CAB infrastructure in the client side (c# .net 2005) Since my application must be sequencally, i wrote all the code in the UI thread. my...
9
by: David | last post by:
Hi all, I posted my question two days ago, and tried to solve this problem. but until now I didn't solve that. and I cut my codes so maybe this time it is more readable. ...
1
by: aboalnodom | last post by:
hello guys, i hope any one will help in this i am designing a web application, the page i am workin on its the default.aspx it contains dropdownboxes the first 4 to choose the type and the...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 4 Oct 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
by: Aliciasmith | last post by:
In an age dominated by smartphones, having a mobile app for your business is no longer an option; it's a necessity. Whether you're a startup or an established enterprise, finding the right mobile app...
0
tracyyun
by: tracyyun | last post by:
Hello everyone, I have a question and would like some advice on network connectivity. I have one computer connected to my router via WiFi, but I have two other computers that I want to be able to...
2
by: giovanniandrean | last post by:
The energy model is structured as follows and uses excel sheets to give input data: 1-Utility.py contains all the functions needed to calculate the variables and other minor things (mentions...
1
by: Teri B | last post by:
Hi, I have created a sub-form Roles. In my course form the user selects the roles assigned to the course. 0ne-to-many. One course many roles. Then I created a report based on the Course form and...
3
by: nia12 | last post by:
Hi there, I am very new to Access so apologies if any of this is obvious/not clear. I am creating a data collection tool for health care employees to complete. It consists of a number of...
0
isladogs
by: isladogs | last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, Mike...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.