Overloading Operator<<
Author |
Message |
The_$hit
|
Posted: Wed Apr 27, 2005 8:48 pm Post subject: Overloading Operator<< |
|
|
Does any one know how to overload the operator << or >> to use it for std::cout or std::cin? I got an understanding of how to do it but my compilier wont let me have 2 parameters when i overload operators.
right now it looks like this:
code: |
ostream& operator<<(ostream& os) {return os<<*this->itsString;}
|
|
|
|
|
|
|
Sponsor Sponsor
|
|
|
wtd
|
Posted: Wed Apr 27, 2005 9:01 pm Post subject: (No subject) |
|
|
This really should be in C/C++ Help, but here's a simple example. You need to use a friend function.
c++: | #include <iostream>
class foo
{
private:
int a;
public:
foo(int i_a) : a(i_a) { }
friend std::ostream& operator<<(std::ostream& out, const foo& f);
};
std::ostream& operator<<(std::ostream& out, const foo& f)
{
return out << f.a;
} |
|
|
|
|
|
|
The_$hit
|
Posted: Thu Apr 28, 2005 10:26 am Post subject: (No subject) |
|
|
CodeWarrior 8 won't let me overload this operator with two parameters. that is why I had to use the *this->. there are no syntax errors but it would let me cout<< the object. |
|
|
|
|
|
wtd
|
Posted: Thu Apr 28, 2005 11:53 am Post subject: (No subject) |
|
|
Did you try exactly the code I gave you? Can you give us the exact contents of the error message? |
|
|
|
|
|
The_$hit
|
Posted: Thu Apr 28, 2005 4:25 pm Post subject: (No subject) |
|
|
Thank you it works. I was missing the friend, it was giving me the message "illigal 'operator' decleration". when i added friend the message stopped. had to be friend function to do that. |
|
|
|
|
|
wtd
|
Posted: Thu Apr 28, 2005 4:34 pm Post subject: (No subject) |
|
|
Yes, a friend function is basically one which lives outside of the class. In this case, the insertion ( << ) and extraction ( >> ) operators are not members of the class. However they are friends, and this is important because that status allows them to access private and protected members of the class. |
|
|
|
|
|
The_$hit
|
Posted: Thu Apr 28, 2005 4:59 pm Post subject: (No subject) |
|
|
ooo ok. So how would you make it so that you can cin an object is this right
code: |
friend std::ostream& operator>>(std::ostream& out, String& temp){char * blah=new char[80];cin>>blah;for (int i=0;i<strlen(blah);i++) temp.setLetter(i,blah[i]);temp.setLetter(strlen(blah),'\0');}
|
|
|
|
|
|
|
wtd
|
Posted: Thu Apr 28, 2005 5:25 pm Post subject: (No subject) |
|
|
First off, let's clean this up.
c++: | friend std::ostream& operator>>(std::ostream& out, String& temp)
{
char * blah = new char[80];
cin >> blah;
for (int i(0); i< strlen(blah); ++i)
temp.setLetter(i, blah[i]);
temp.setLetter(strlen(blah), '\0');
} |
Now, let's look at what's wrong here.
First, you only use the friend when declaring the function within the class. In this case your String class.
Next, you're using the sd::ostream class. We're not outputting, so we need to use the std::istream class.
Also, you're referring to cin, even though you have a stream variable to work with passed as an argument to the function.
c++: | std::istream& operator>>(std::istream& in, String& temp)
{
char * blah = new char[80];
in >> blah;
for (int i(0); i< strlen(blah); ++i)
temp.setLetter(i, blah[i]);
temp.setLetter(strlen(blah), '\0');
} |
Now, to go any further, I need to see your String class. Let me guess though, it looks looks a bit like:
c++: | #include <iostream>
#include <cstring>
class String
{
private:
// store the characters
char * buffer;
public:
// default constructor
String();
// copy constructor
String(const String& other);
// destructor
~String();
// get a letter at a particular index
char letter(size_t index) const;
// get a reference to a letter at a particular position
// changes to a letter can be made with something like:
// some_string.letter(43) = 'A';
char& letter(size_t index);
friend std::ostream& operator<<(std::ostream& out, const String& s);
friend std::istream& operator>>(std::istream& out, String& s);
};
String::String() : buffer(new char[80]) { }
String::String(const String& other) : buffer(new char[80])
{
std::copy(other.buffer, other.buffer + 80, buffer);
}
String::~String()
{
delete [] buffer;
}
char String::letter(size_t index) const
{
return buffer[index];
}
char& String::letter(size_t index)
{
return buffer[index];
} |
A final note for this post: why are you doing this? Standard C++ provides a perfectly good string class in std::string. |
|
|
|
|
|
Sponsor Sponsor
|
|
|
The_$hit
|
Posted: Thu Apr 28, 2005 9:10 pm Post subject: (No subject) |
|
|
I am doing this class so i can customize it and i know all of the functions in it. It is also for good for practice with overloading operators, arrays, i was also thinking that it would help me understand pointers.
code: |
#include <iostream>
using namespace std;
class String
{
public:
String(){itsString=new char[1];itsString[0]='\0';itsLength=1;}
String(String & temp){itsLength=temp.getLength();itsString=new
char[itsLength];for(int x=0;x<itsLength;x++)
itsString[x]=temp[x];itsString[itsLength]='\0';}
String(String & temp,char * tempo){itsLength=temp.getLength()+strlen(tempo);itsString=new char[itsLength];for(int x=0;x<itsLength;x++) itsString[x]=temp[x];itsString[itsLength]='\0';}
String(char * temp){itsLength=strlen(temp);itsString=new char[itsLength];for(int x=0;x<itsLength;x++) itsString[x]=temp[x];itsString[itsLength]='\0';}
char operator[](int amount){return itsString[amount];}
void setLetter(int letter,char cha) {itsString[letter]=cha;}
char * operator() () {*this+=" ";return " ";}
ostream& operator<<(ostream& os) {return os<<*this->itsString;}
String operator=(String & temp){ delete[] itsString;itsLength=temp.getLength();itsString=new char[itsLength+1];for(int x=0;x<itsLength;x++) itsString[x]=temp[x];itsString[itsLength]='\0';return *this;}
String operator=(char * temp){ delete[] itsString;itsLength=strlen(temp);itsString=new char[itsLength];for(int x=0;x<itsLength;x++) itsString[x]=temp[x]; itsString[itsLength]='\0';return *this;}
String operator+=(char * temp){int tot=strlen(temp)+itsLength;String blah(*this);delete [] itsString;itsString=new char[tot];int x;for (x=0;x<itsLength;x++) itsString[x]=blah[x];for (int i=0;x<tot;x++,i++) itsString[x]=temp[i];itsString[tot]='\0';itsLength=tot;return *this;}
char * operator+(char * temp){int tot=strlen(temp)+itsLength;char * tempu=new char[tot];int x;for (x=0;x<itsLength;x++) tempu[x]=itsString[x];for (int i=0;x<tot;x++,i++) tempu[x]=temp[i];tempu[tot]='\0'; return tempu;}
String operator+=(String & temp){int tot=temp.getLength()+itsLength;String blah(*this);delete [] itsString;itsString=new char[tot];int x;for (x=0;x<itsLength;x++) itsString[x]=blah[x];for (int i=0;x<tot;x++,i++) itsString[x]=temp[i];itsString[tot]='\0';itsLength=tot;return *this;}
char * operator+(String & temp){int tot=temp.getLength()+itsLength;char * tempu=new char[tot];int x;for (x=0;x<itsLength;x++) tempu[x]=itsString[x];for (int i=0;x<tot;x++,i++) tempu[x]=temp[i];tempu[tot]='\0'; return tempu;}
int getLength() {return itsLength;}
char * getString() {return itsString;}
friend std::ostream& operator<<(std::ostream& out, const String& temp)
{return out <<temp.itsString;}
/*friend std::ostream& operator>>(std::ostream& out, String& temp){char * blah=new char[80];blah;for (int i=0;i<strlen(blah);i++) temp.setLetter(i,blah[i]);temp.setLetter(strlen(blah),'\0');}*/
private:
String(int num){itsLength=num;itsString=new char[num];for (int x=0;x<itsLength;x++) itsString[x]='\0';}
int itsLength;
char * itsString;
};
|
|
|
|
|
|
|
wtd
|
Posted: Thu Apr 28, 2005 10:01 pm Post subject: (No subject) |
|
|
You'll find help far more forthcoming if you post well-formatted code.
c++: | #include <iostream>
using namespace std;
class String
{
public:
String()
{
itsString = new char[1];
itsString[0] = '\0';
itsLength=1;
}
String(String& temp)
{
itsLength = temp.getLength();
itsString = new char[itsLength];
for (int x = 0; x < itsLength; x++)
itsString[x] = temp[x];
itsString[itsLength] = '\0';
}
String(String& temp, char *tempo)
{
itsLength = temp.getLength() + strlen(tempo);
itsString = new char[itsLength];
for (int x = 0; x < itsLength; x++)
itsString[x] = temp[x];
itsString[itsLength] = '\0';
}
String(char *temp)
{
itsLength = strlen(temp);
itsString = new char[itsLength];
for (int x = 0; x < itsLength; x++)
itsString[x] = temp[x];
itsString[itsLength] = '\0';
}
char operator[](int amount)
{
return itsString[amount];
}
void setLetter(int letter, char cha)
{
itsString[letter] = cha;
}
char *operator()()
{
*this += " ";
return " ";
}
ostream& operator<<(ostream& os)
{
return os << *this->itsString;
}
String operator=(String& temp)
{
delete [] itsString;
itsLength = temp.getLength();
itsString = new char[itsLength + 1];
for (int x = 0; x < itsLength; x++)
itsString[x] = temp[x];
itsString[itsLength] = '\0';
return *this;
}
String operator=(char *temp)
{
delete [] itsString;
itsLength = strlen(temp);
itsString = new char[itsLength];
for (int x = 0; x < itsLength; x++)
itsString[x] = temp[x];
itsString[itsLength] = '\0';
return *this;
}
String operator+=(char *temp)
{
int tot = strlen(temp) + itsLength;
String blah(*this);
delete [] itsString;
itsString = new char[tot];
int x;
for (x = 0; x < itsLength; x++)
itsString[x] = blah[x];
for (int i = 0; x < tot; x++, i++)
itsString[x] = temp[i];
itsString[tot] = '\0';
itsLength = tot;
return *this;
}
char *operator+(char *temp)
{
int tot = strlen(temp) + itsLength;
char *tempu = new char[tot];
int x;
for (x = 0; x < itsLength; x++)
tempu[x] = itsString[x];
for (int i = 0; x < tot; x++, i++)
tempu[x] = temp[i];
tempu[tot] = '\0';
return tempu;
}
String operator+=(String& temp)
{
int tot = temp.getLength() + itsLength;
String blah(*this);
delete [] itsString;
itsString = new char[tot];
int x;
for (x = 0; x < itsLength; x++)
itsString[x] = blah[x];
for (int i = 0; x < tot; x++, i++)
itsString[x] = temp[i];
itsString[tot] = '\0';
itsLength = tot;
return *this;
}
char *operator+(String& temp)
{
int tot = temp.getLength() + itsLength;
char *tempu = new char[tot];
int x;
for (x = 0; x < itsLength; x++)
tempu[x] = itsString[x];
for (int i = 0; x < tot; x++, i++)
tempu[x] = temp[i];
tempu[tot] = '\0';
return tempu;
}
int getLength()
{
return itsLength;
}
char *getString()
{
return itsString;
}
friend std::ostream& operator<<(std::ostream& out, const String& temp)
{
return out << temp.itsString;
}
/*
friend std::ostream& operator>>(std::ostream& out, String& temp)
{
char *blah = new char[80];
blah;
for (int i = 0; i < strlen(blah); i++)
temp.setLetter(i, blah[i]);
temp.setLetter(strlen(blah), '\0');
}
*/
private:
String(int num)
{
itsLength = num;
itsString = new char[num];
for (int x = 0; x < itsLength; x++)
itsString[x] = '\0';
}
int itsLength;
char *itsString;
}; |
|
|
|
|
|
|
The_$hit
|
Posted: Fri Apr 29, 2005 9:04 pm Post subject: (No subject) |
|
|
This program does not let me cin the object. there are no syntax errors in theclass but when you cin << a String it returns this error: illegal operands 'std::basic_istream<char,std::char_traits<chars>>' >> 'String' |
|
|
|
|
|
wtd
|
Posted: Fri Apr 29, 2005 9:57 pm Post subject: (No subject) |
|
|
Ok, let's look at a very simple example of overloading the extraction ( >> ) operator.
c++: | class foo
{
private:
int a;
public:
int get_a() const;
friend std::istream& operator>>(std::istream& in, foo& f);
};
int foo::get_a() const
{
return a;
}
std::istream& operator>>(std::istream& in, foo& f)
{
in >> f.a;
return in;
} |
So, what am I doing here? Well, I have a class "foo" with a private instance variable "a" which is an int. I have a public method "get_a()" to retrieve that value. I also have a friend, which is the extaction operator.
The implementation of get_a() is so simple it warrants no further mention.
Now, when I implement the extraction operator, it isn't a member of the foo class. Rather it takes the input stream and a reference to a foo object. The operator reads into that object's "a" instance variable, and then the input stream is returned, allowing for chaining them together, like so:
c++: | foo b, c, d, e, f;
std::cin >> b >> c >> d >> e >> f; |
Any questions? |
|
|
|
|
|
The_$hit
|
Posted: Sat Apr 30, 2005 12:15 am Post subject: (No subject) |
|
|
Thank you very much for all of your help. My completed String class is here:
code: |
//Created By: Julian Haldenby
#include <iostream>
using namespace std;
class String
{
public:
String(){
itsString=new char[1];
itsString[0]='\0';
itsLength=1;
}
String(String & temp){
itsLength=temp.getLength();
itsString=new char[itsLength];
for(int x=0;x<itsLength;
x++) itsString[x]=temp[x];
itsString[itsLength]='\0';
}
String(String & temp,char * tempo){
itsLength=temp.getLength()+strlen(tempo);
itsString=new char[itsLength];
for(int x=0;x<itsLength;x++) itsString[x]=temp[x];
itsString[itsLength]='\0';
}
String(char * temp){
itsLength=strlen(temp);
itsString=new char[itsLength];
for(int x=0;x<itsLength;x++) itsString[x]=temp[x];
itsString[itsLength]='\0';
}
char operator[](int amount){
return itsString[amount];
}
void setLetter(int letter,char cha) {
itsString[letter]=cha;
}
char * operator() () {
*this+=" ";return " ";
}
bool operator== (char * temp) {
if (!itsLength==strlen(temp)) return false;
else {for (int x=0;x<itsLength;x++)
{if (!itsString[x]==temp[x]) {return false;}}}return true;
}
bool operator== (String & temp) {
if (!itsLength==temp.getLength()) return false;
else {for (int x=0;x<itsLength;x++)
{if (!itsString[x]==temp[x]) {return false;}}}return true;
}
String operator=(String & temp){
delete[] itsString;
itsLength=temp.getLength();
itsString=new char[itsLength+1];
for(int x=0;x<itsLength;x++) itsString[x]=temp[x];
itsString[itsLength]='\0';
return *this;
}
String operator=(char * temp){
delete[] itsString;
itsLength=strlen(temp);
itsString=new char[itsLength];
for(int x=0;x<itsLength;x++) itsString[x]=temp[x];
itsString[itsLength]='\0';
return *this;
}
String operator+=(char * temp){
int tot=strlen(temp)+itsLength;
String blah(*this);
delete [] itsString;
itsString=new char[tot];
int x;
for (x=0;x<itsLength;x++) itsString[x]=blah[x];
for (int i=0;x<tot;x++,i++) itsString[x]=temp[i];
itsString[tot]='\0';itsLength=tot;
return *this;
}
char * operator+(char * temp){
int tot=strlen(temp)+itsLength;
char * tempu=new char[tot];
int x;
for (x=0;x<itsLength;x++) tempu[x]=itsString[x];
for (int i=0;x<tot;x++,i++) tempu[x]=temp[i];
tempu[tot]='\0';
return tempu;
}
String operator+=(String & temp){
int tot=temp.getLength()+itsLength;
String blah(*this);
delete [] itsString;
itsString=new char[tot];
int x;
for (x=0;x<itsLength;x++) itsString[x]=blah[x];
for (int i=0;x<tot;x++,i++) itsString[x]=temp[i];
itsString[tot]='\0';
itsLength=tot;
return *this;
}
char * operator+(String & temp){
int tot=temp.getLength()+itsLength;
char * tempu=new char[tot];
int x;for (x=0;x<itsLength;x++) tempu[x]=itsString[x];
for (int i=0;x<tot;x++,i++) tempu[x]=temp[i];
tempu[tot]='\0';
return tempu;
}
int getLength() {
return itsLength;
}
friend std::istream& operator>>(std::istream& in, String& f){
f.buffer=new char[100];
in >> f.buffer;
delete [] f.itsString;
f.itsLength=strlen(f.buffer);
for (int x=0;x<f.itsLength;x++) f.itsString[x]=f.buffer[x];
delete[] f.buffer;
return in;
}
friend std::ostream& operator<<(std::ostream& out, const String& temp){
return out <<temp.itsString;
}
private:
String(int num){
itsLength=num;
itsString=new char[num];
for (int x=0;x<itsLength;x++) itsString[x]='\0';
}
int itsLength;
char * buffer;
char * itsString;
};
|
**** Edit hmmmmm.... soething is wrong? My console debug quits automatically |
|
|
|
|
|
wtd
|
Posted: Sat Apr 30, 2005 12:52 am Post subject: (No subject) |
|
|
Tips:
- In a constructor, there is specific syntax for initializing instance variables. Rather than:
c++: | String()
{
itsString=new char[1];
itsString[0]='\0';
itsLength=1;
} |
We have:
c++: | String()
: itsString(new char[1])
, itsLength(1)
{
itsString[0]='\0';
} |
Omit the null terminator. You know the length of your string, so there's no need for a null character to terminate it.
Use 'const' qualifiers where appropriate. Consider:
c++: | int getLength()
{
return itsLength;
} |
This member function ("method") doesn't change the object in any way. It is therefore safe to call this method on a const String, so we need to tell the compiler that.
c++: | int getLength() const
{
return itsLength;
} |
Rework these:
c++: | char operator[](int amount)
{
return itsString[amount];
}
void setLetter(int letter, char cha)
{
itsString[letter] = cha;
} |
For the first, we're not changing the object, so we can add a const qualifier.
c++: | char operator[](int amount) const
{
return itsString[amount];
} |
Now, for the second, and to make our class feel nicer to work with, let's reuse the bracket operator. To differentiate the two, we'll say that one can be called in a const situation, and the other in a non-const situation.
The fact that it returns a reference means we can assign to it.
c++: | char& operator[](int letter)
{
return itsString[letter];
} |
Next up, instead of using "int" for indexes, let's use the standard size type: "size_t".
c++: | char operator[](size_t amount) const
{
return itsString[amount];
}
char& operator[](size_t letter)
{
return itsString[letter];
} |
With your arrays, you're dynamically allocating memory. That means your class needs a destructor which frees that memory.
Last but not least... separate the declaration and definition of your class. Have a String.h file containing:
c++: | #include <iostream>
using namespace std;
class String
{
public:
String();
String(String& temp);
String(String& temp, const char *tempo);
String(const char *temp);
char operator[](size_t amount) const;
char& operator[](size_t letter);
char * operator()();
bool operator==(const char *temp) const;
bool operator==(const String& temp);
String operator=(const String& temp);
String operator=(const char *temp);
String operator+=(const char *temp);
String operator+=(const String& temp);
char *operator+(char *temp) const;
char *operator+(const String& temp) const;
size_t getLength() const;
friend std::istream& operator>>(std::istream& in, String& f);
friend std::ostream& operator<<(std::ostream& out, const String& temp);
private:
String(const size_t num);
size_t itsLength;
char * buffer;
char * itsString;
}; |
And then a String.cpp file which contains all of the member function definitions. |
|
|
|
|
|
|
|