PDA

View Full Version : C++:Help with Class operator Overloading, copy-constructors etc




Soulstorm
Jul 9, 2006, 04:29 PM
I am trying to recreate a class that will simulate an STL string. So far, I have had no problems. Here is my class, named stash
stash.h#ifndef STASH_H
#define STASH_H
#include <iostream>
#include <string>

#define MasterStringBuild 30
#define MasterStringBuildString "Beta Build"

#define next currentStorage - currentSize
#define STDstring std::string
#define STDostream std::ostream
#define STDistream std::istream

//TO BE EXTENSIVELY TESTED AND REVISED BEFORE RELEASE!!!!!!!!!!

class stash;
typedef stash MasterString; //New Definition for the Stash

class stash{
char *ch;
unsigned int currentSize; //position of the last character
unsigned int currentStorage; //size of the entire array
//unsigned int next;
public:

//constructors
stash();
stash(unsigned int startSize);
stash(char *p);
stash(stash &other); //copy constructor
~stash();

//main functions
void show();
void inflate();
void add(char p);
void insertString(const char *p);
void insertSTLString(STDstring s);
char* returnAsString();
void resetStash();

//information getters
char returnCharacterAtPosition(unsigned int i);
int returnCurrentSize(){return currentSize;}
int returnCurrentStorage(){return currentStorage;}
STDstring returnAsSTLString();
//int returnNext(){return next;}
char* returnPointerToCh(){return ch;}

//overloaded operators
void operator+(const char *p);
void operator+(stash& s);
void operator+(char s);

void operator=(const char *p);
void operator=(stash s);
void operator=(STDstring &s);

char operator[](unsigned int i);

bool operator==(stash s);
bool operator==(const char *p);
bool operator==(STDstring s);

//miscellaneous editing
void appendString(stash &s);
void appendString(char *CStyleString);
void appendString(STDstring s);

void insertStringAtPosition(stash &s, unsigned int pos);
void insertStringAtPosition(char *CStyleString, unsigned int pos);
void insertStringAtPosition(STDstring s, unsigned int pos);

STDstring returnRangeAsSTLString(unsigned int startPos, unsigned int endPos);
stash returnRangeAsStash(unsigned int startPos, unsigned int endPos);

void deleteCharactersBetweenIndex(unsigned int startIndex, unsigned int endIndex);

friend STDostream &operator<<(STDostream &stream, stash &ob);
friend STDistream &operator>>(STDistream &stream, stash &ob);

//build informative functions
int returnCurrentMasterStringBuild();
};

#endif
and stash.cpp:
#include <iostream>
#include "stash.h"
#include <string>

using std::cout;

int gIncrement = 8; //Number of bytes to add each time the class is expanded
//Smaller numbers guarantee less memory consuption, but
//also a small performance hit.

//**constructors and destructors
stash::stash(){
ch = 0; //allocate zero to initialize the 'ch' pointer'
resetStash();
}

stash::stash(unsigned int startSize){
ch = new char [startSize];
currentSize = 0;
currentStorage = startSize;
//next = currentStorage - currentSize;
}

stash::~stash(){
delete [] ch;
cout << "Freeing storage\n"; //**for debugging purposes only
}

stash::stash(char *p){
ch = 0;
resetStash();
insertString(p);
}

stash::stash(stash &other){
ch = 0;
resetStash();
insertString(other.returnPointerToCh());
}

//*******

//Show the elements of the class
void stash::show(){
cout << "currentStorage: " << currentStorage << "\n";
cout << "current size: " << currentSize << "\n";
cout << "Next: " << next << "\n";
for(int i=0; i<currentSize; i++)
cout << ch[i];
cout << "\n";
}

//--Increase the stash's size to hold more chars.
void stash::inflate(){
int i;
char *temp = new char [currentSize + gIncrement];
for(i=0; i<currentSize; i++)
temp[i] = ch[i];
delete [] ch;
ch = temp;
currentStorage = currentStorage + gIncrement;
}

//--add a character to the stash and resize it according
//--to space needed
void stash::add(char p){
if(next == 0)
inflate();
ch[currentSize] = p;
++currentSize;
//next = currentStorage - currentSize;
}

//--reset the stash
void stash::resetStash(){
if(ch)
delete [] ch;
ch = new char [gIncrement];
currentSize = 0;
currentStorage = gIncrement;
//next = gIncrement - currentSize;
}

//--insert an entire string into the stash
void stash::insertString(const char *p){
int i;
for(i=0; p[i]; i++){
add(p[i]);
}
}

//--Insert an STL string into the MasterString class
void stash::insertSTLString(STDstring s){
int i;
resetStash();
for(i=0; i<s.size(); i++)
add(s[i]);
}

//--make the chars a string
char* stash::returnAsString(){
add('\0');
//next--;
currentSize--;
return ch;
}

//--return the masterstring as an STL string
STDstring stash::returnAsSTLString(){
return STDstring(returnAsString());
}

//--add more chars into the string;
void stash::operator+(const char *p){
insertString(p);
}

//--experimental: add 2 MasterStrings
//--add more chars into the string;
void stash::operator+(stash &s){
insertString(s.returnAsString());
}

void stash::operator+(char s){
add(s);
}

//--Return a character at a specified position
//--Return NULL if a character doesn't exist at the
//--requested position
char stash::returnCharacterAtPosition(unsigned int i){
if(i>currentSize)
return NULL;
return ch[i];
}

//--clear the stash and hold a new string
void stash::operator=(const char *p){
resetStash();
insertString(p);
}

//--make a string hold exactly what the other holds!!!
void stash::operator=(stash s){
int i;
delete [] ch; //delete before assignment
char *temp = new char [s.returnCurrentSize()];
for(i=0; i<s.returnCurrentSize(); i++){
temp[i] = s.returnCharacterAtPosition(i);
}
//next = s.returnNext();
currentStorage = s.returnCurrentStorage();
currentSize = s.returnCurrentSize();
ch = temp;
}

//--make the MasterString hold an STL string
//--with the '=' operator
void stash::operator=(STDstring &s){
insertSTLString(s);
}

//--Return a character at a specified integer position
char stash::operator[](unsigned int i){
return returnCharacterAtPosition(i);
}

//--Compare two stashes together
bool stash::operator==(stash s){
if(strcmp(s.returnPointerToCh(),ch))
return 0;
return 1;
}

//--Compare a stash with a const char
bool stash::operator==(const char *p){
if(strcmp(p,ch))
return 0;
return 1;
}

//--Compare a stash with an STL string
bool stash::operator==(STDstring s){
if(strcmp(s.c_str(),ch))
return 0;
return 1;
}

//--Overloaded appendString function
//--TO BE TESTED!
void stash::appendString(stash &s){
int i;
for(i=0; i<s.returnCurrentSize(); i++){
add(s[i]);
}
}

void stash::appendString(char *CStyleString){
int i;
for(i=0; i<strlen(CStyleString); i++){
add(CStyleString[i]);
}
}

void stash::appendString(STDstring s){
int i;
for(i=0; i<s.size(); i++){
add(s[i]);
}
}
//**

//--Insert Strings At Positions:
void stash::insertStringAtPosition(char *CStyleString, unsigned int pos){
STDstring result(CStyleString);
insertStringAtPosition(result,pos);
}

void stash::insertStringAtPosition(stash &s, unsigned int pos){
insertStringAtPosition(s.returnAsSTLString(),pos);
}

void stash::insertStringAtPosition(STDstring s, unsigned int pos){
STDstring result;
int i;
for(i=0; i<=pos; i++){
result = result + ch[i];
}
for (i=0; i<s.size(); i++) {
result = result + s[i];
}
for (i=pos+1; i<(returnCurrentSize()); i++) {
result = result + ch[i];
}
*this = result; //assign the new masterstring to self

}
//**

//--Return a range of characters inside the MasterString
//--as an STDstring
STDstring stash::returnRangeAsSTLString(unsigned int startPos, unsigned int endPos){
STDstring result;
int i;
for(i=startPos; i<endPos; i++){
result = result + ch[i];
}
return result;
}

//THIS FUNCTION HAS PROBLEMS!!!!!
stash stash::returnRangeAsStash(unsigned int startPos, unsigned int endPos){
stash result;
int i;
for(i=startPos; i<endPos; i++){
result + ch[i];
}
cout << result;
return result;
}

//--Delete characters inside the MasterString that are
//--between a given index
void stash::deleteCharactersBetweenIndex(unsigned int startIndex, unsigned int endIndex){
STDstring result;
int i;
for(i=0; i<startIndex; i++){
result = result + ch[i];
}
for(i=endIndex; i<currentSize; i++){
result = result + ch[i];
}
insertSTLString(result);
}



/***************************Informative Functions*****************************/
int returnCurrentMasterStringBuild(){
return MasterStringBuild;
}

/***************************Friendly functions********************************/
//--Overloaded operator <<
STDostream &operator<<(STDostream &stream, stash &ob){
int i;
for(i=0; i<ob.currentSize; i++){
stream << ob.returnCharacterAtPosition(i);
}
return stream;
}

//--Experimental: overloaded operator >>
STDistream &operator>>(STDistream &stream, stash &ob){
STDstring s;
getline(stream,s);
ob.insertSTLString(s);
return stream;
}


try using this main, and you will get errors:
#include <iostream>
#include "stash.h"
using namespace std;

int main(){
MasterString s("0123456789");
s.deleteCharactersBetweenIndex(3,8);
MasterString k;

k = s.returnRangeAsStash(3,6);

cout << k;
return 0;
}
The error I get is this:
main.cpp:10: error: initializing argument 1 of 'void stash::operator=(stash)'
main.cpp:10: error: no matching function for call to 'stash::stash(stash)'
stash.h:36: note: stash::stash(unsigned int)
stash.h:37: note: stash::stash(char*)
stash.h:38: note: candidates are: stash::stash(stash&)
Why is that? Why am I getting these errors?



Soulstorm
Jul 9, 2006, 04:29 PM
Also, can anyone tell me why the Compiler doesn't let me change my copy constructor and put 'const stash& other' as an argument? It only lets me put 'stash& other' as an argument because if I put the other one, it gets me an error aboutstash.cpp:48: error: passing 'const stash' as 'this' argument of 'char* stash::returnPointerToCh()' discards qualifiers
at this function: stash::stash(const stash &other){
ch = 0;
resetStash();
insertString(other.returnPointerToCh());
}

slooksterPSV
Jul 10, 2006, 01:31 AM
906Freeing storage
0xbffff97c

That's the output I got when I changed these lines:
Ok now understand this, there is no call for stash::stash(stash) only a reference (right?) to stash::stash(stash &)

So you need to return Pointers, think about when you do k = s.return...
that's using the constructor stash(stash) which does not exist
If you do k = s->return...
it works. Here's the updated code:


//main.cpp
#include <iostream>
#include "stash.h"

using namespace std;

int main(){
//char* number = "0123456789";
MasterString *s = new MasterString("1234567890");
s->deleteCharactersBetweenIndex(3,8);
MasterString *k;

k = s->returnRangeAsStash(3, 6);

cout << k << endl;
return 0;
}


Stash.h

//stash.h
#ifndef STASH_H
#define STASH_H
#include <iostream>
#include <string>

#define MasterStringBuild 30
#define MasterStringBuildString "Beta Build"

#define next currentStorage - currentSize
#define STDstring std::string
#define STDostream std::ostream
#define STDistream std::istream

//TO BE EXTENSIVELY TESTED AND REVISED BEFORE RELEASE!!!!!!!!!!

class stash;
typedef stash MasterString; //New Definition for the Stash

class stash{
char *ch;
unsigned int currentSize; //position of the last character
unsigned int currentStorage; //size of the entire array
//unsigned int next;
public:

//constructors
stash();
stash(unsigned int startSize);
stash(char *p);
stash(stash &other); //copy constructor

~stash();

//main functions
void show();
void inflate();
void add(char p);
void insertString(const char *p);
void insertSTLString(STDstring s);
char* returnAsString();
void resetStash();

//information getters
char returnCharacterAtPosition(unsigned int i);
int returnCurrentSize(){return currentSize;}
int returnCurrentStorage(){return currentStorage;}
STDstring returnAsSTLString();
//int returnNext(){return next;}
char* returnPointerToCh(){return ch;}

//overloaded operators
void operator+(const char *p);
void operator+(stash& s);
void operator+(char s);

void operator=(const char *p);
void operator=(stash s);
void operator=(STDstring &s);

char operator[](unsigned int i);

bool operator==(stash s);
bool operator==(const char *p);
bool operator==(STDstring s);

//miscellaneous editing
void appendString(stash &s);
void appendString(char *CStyleString);
void appendString(STDstring s);

void insertStringAtPosition(stash &s, unsigned int pos);
void insertStringAtPosition(char *CStyleString, unsigned int pos);
void insertStringAtPosition(STDstring s, unsigned int pos);

STDstring returnRangeAsSTLString(unsigned int startPos, unsigned int endPos);
stash *returnRangeAsStash(unsigned int startPos, unsigned int endPos);

void deleteCharactersBetweenIndex(unsigned int startIndex, unsigned int endIndex);

friend STDostream &operator<<(STDostream &stream, stash &ob);
friend STDistream &operator>>(STDistream &stream, stash &ob);

//build informative functions
int returnCurrentMasterStringBuild();
};

#endif


stash.cpp

//stash.cpp
#include <iostream>
#include "stash.h"
#include <string>

using std::cout;

int gIncrement = 8; //Number of bytes to add each time the class is expanded
//Smaller numbers guarantee less memory consuption, but
//also a small performance hit.

//**constructors and destructors
stash::stash(){
ch = 0; //allocate zero to initialize the 'ch' pointer'
resetStash();
}

stash::stash(unsigned int startSize){
ch = new char [startSize];
currentSize = 0;
currentStorage = startSize;
//next = currentStorage - currentSize;
}

stash::~stash(){
delete [] ch;
cout << "Freeing storage\n"; //**for debugging purposes only
}

stash::stash(char *p){
ch = 0;
resetStash();
insertString(p);
}

stash::stash(stash &other){
ch = 0;
resetStash();
insertString(other.returnPointerToCh());
}

//*******

//Show the elements of the class
void stash::show(){
cout << "currentStorage: " << currentStorage << "\n";
cout << "current size: " << currentSize << "\n";
cout << "Next: " << next << "\n";
for(int i=0; i<currentSize; i++)
cout << ch[i];
cout << "\n";
}

//--Increase the stash's size to hold more chars.
void stash::inflate(){
int i;
char *temp = new char [currentSize + gIncrement];
for(i=0; i<currentSize; i++)
temp[i] = ch[i];
delete [] ch;
ch = temp;
currentStorage = currentStorage + gIncrement;
}

//--add a character to the stash and resize it according
//--to space needed
void stash::add(char p){
if(next == 0)
inflate();
ch[currentSize] = p;
++currentSize;
//next = currentStorage - currentSize;
}

//--reset the stash
void stash::resetStash(){
if(ch)
delete [] ch;
ch = new char [gIncrement];
currentSize = 0;
currentStorage = gIncrement;
//next = gIncrement - currentSize;
}

//--insert an entire string into the stash
void stash::insertString(const char *p){
int i;
for(i=0; p[i]; i++){
add(p[i]);
}
}

//--Insert an STL string into the MasterString class
void stash::insertSTLString(STDstring s){
int i;
resetStash();
for(i=0; i<s.size(); i++)
add(s[i]);
}

//--make the chars a string
char* stash::returnAsString(){
add('\0');
//next--;
currentSize--;
return ch;
}

//--return the masterstring as an STL string
STDstring stash::returnAsSTLString(){
return STDstring(returnAsString());
}

//--add more chars into the string;
void stash::operator+(const char *p){
insertString(p);
}

//--experimental: add 2 MasterStrings
//--add more chars into the string;
void stash::operator+(stash &s){
insertString(s.returnAsString());
}

void stash::operator+(char s){
add(s);
}

//--Return a character at a specified position
//--Return NULL if a character doesn't exist at the
//--requested position
char stash::returnCharacterAtPosition(unsigned int i){
if(i>currentSize)
return NULL;
return ch[i];
}

//--clear the stash and hold a new string
void stash::operator=(const char *p){
resetStash();
insertString(p);
}

//--make a string hold exactly what the other holds!!!
void stash::operator=(stash s){
int i;
delete [] ch; //delete before assignment
char *temp = new char [s.returnCurrentSize()];
for(i=0; i<s.returnCurrentSize(); i++){
temp[i] = s.returnCharacterAtPosition(i);
}
//next = s.returnNext();
currentStorage = s.returnCurrentStorage();
currentSize = s.returnCurrentSize();
ch = temp;
}

//--make the MasterString hold an STL string
//--with the '=' operator
void stash::operator=(STDstring &s){
insertSTLString(s);
}

//--Return a character at a specified integer position
char stash::operator[](unsigned int i){
return returnCharacterAtPosition(i);
}

//--Compare two stashes together
bool stash::operator==(stash s){
if(strcmp(s.returnPointerToCh(),ch))
return 0;
return 1;
}

//--Compare a stash with a const char
bool stash::operator==(const char *p){
if(strcmp(p,ch))
return 0;
return 1;
}

//--Compare a stash with an STL string
bool stash::operator==(STDstring s){
if(strcmp(s.c_str(),ch))
return 0;
return 1;
}

//--Overloaded appendString function
//--TO BE TESTED!
void stash::appendString(stash &s){
int i;
for(i=0; i<s.returnCurrentSize(); i++){
add(s[i]);
}
}

void stash::appendString(char *CStyleString){
int i;
for(i=0; i<strlen(CStyleString); i++){
add(CStyleString[i]);
}
}

void stash::appendString(STDstring s){
int i;
for(i=0; i<s.size(); i++){
add(s[i]);
}
}
//**

//--Insert Strings At Positions:
void stash::insertStringAtPosition(char *CStyleString, unsigned int pos){
STDstring result(CStyleString);
insertStringAtPosition(result,pos);
}

void stash::insertStringAtPosition(stash &s, unsigned int pos){
insertStringAtPosition(s.returnAsSTLString(),pos);
}

void stash::insertStringAtPosition(STDstring s, unsigned int pos){
STDstring result;
int i;
for(i=0; i<=pos; i++){
result = result + ch[i];
}
for (i=0; i<s.size(); i++) {
result = result + s[i];
}
for (i=pos+1; i<(returnCurrentSize()); i++) {
result = result + ch[i];
}
*this = result; //assign the new masterstring to self

}
//**

//--Return a range of characters inside the MasterString
//--as an STDstring
STDstring stash::returnRangeAsSTLString(unsigned int startPos, unsigned int endPos){
STDstring result;
int i;
for(i=startPos; i<endPos; i++){
result = result + ch[i];
}
return result;
}

//THIS FUNCTION HAS PROBLEMS!!!!!
stash *stash::returnRangeAsStash(unsigned int startPos, unsigned int endPos){
stash result;
int i;
for(i=startPos; i<endPos; i++){
result + ch[i];
}
cout << result;
return &result;
}

//--Delete characters inside the MasterString that are
//--between a given index
void stash::deleteCharactersBetweenIndex(unsigned int startIndex, unsigned int endIndex){
STDstring result;
int i;
for(i=0; i<startIndex; i++){
result = result + ch[i];
}
for(i=endIndex; i<currentSize; i++){
result = result + ch[i];
}
insertSTLString(result);
}



/***************************Informative Functions*****************************/
int returnCurrentMasterStringBuild(){
return MasterStringBuild;
}

/***************************Friendly functions********************************/
//--Overloaded operator <<
STDostream &operator<<(STDostream &stream, stash &ob){
int i;
for(i=0; i<ob.currentSize; i++){
stream << ob.returnCharacterAtPosition(i);
}
return stream;
}

//--Experimental: overloaded operator >>
STDistream &operator>>(STDistream &stream, stash &ob){
STDstring s;
getline(stream,s);
ob.insertSTLString(s);
return stream;
}

[/code]

slooksterPSV
Jul 10, 2006, 01:38 AM
As for your second to comment/q?
const stash &other
you can add that only if you add to the function:
stash temp = other;
...
change
other.return....
to
temp.return...

Soulstorm
Jul 10, 2006, 02:17 AM
As for your second to comment/q?
const stash &other
you can add that only if you add to the function:
stash temp = other;
...
change
other.return....
to
temp.return...
This brings up the debugger because a runtime error has occured. In the debugger I see that all temp and s variables are out of scope. why? this is the new copy-constructor stash::stash(const stash& other){
stash temp = other;
ch = 0;
resetStash();
insertString(temp.returnPointerToCh());
}

slooksterPSV
Jul 10, 2006, 04:47 PM
This brings up the debugger because a runtime error has occured. In the debugger I see that all temp and s variables are out of scope. why? this is the new copy-constructor stash::stash(const stash& other){
stash temp = other;
ch = 0;
resetStash();
insertString(temp.returnPointerToCh());
}

I don't know, it works for me. Is it being compiled as GCC or G++, it needs to be G++

Gil Bates
Jul 10, 2006, 06:22 PM
I think the problem in your 1st post is that you don't have a copy constructor:
stash(const stash &) // (note "const") I don't think stash(stash &) is a copy constructor.


The problems in your 2nd post is that returnPointerToCh() is called for a "const" object while returnPointerToCh() is not "const". You need:
char * returnPointerToCh() const { ... };
This will declare that the function will not modify itself.

Furthermore, you probably should declare it as:
const char * returnPointerToCh() const { ... };
assuming you don't want anyone to modify the returned string from outside of the class.


Also, an assignment operator is usually declared as:
X & X::operator = (const X & other)
{
// copy the contens from other

return *this;
}
It will return itself, not a copy, so you can write like:
(x = y) = z;

This applies for other operators, such as +, +=, etc.

iSee
Jul 10, 2006, 09:16 PM
GB has it exactly right.