Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 Overloading Operator<<
Index -> Programming, C++ -> C++ Help
View previous topic Printable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
The_$hit




PostPosted: 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
Sponsor
sponsor
wtd




PostPosted: 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




PostPosted: 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




PostPosted: 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




PostPosted: 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




PostPosted: 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




PostPosted: 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




PostPosted: 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
Sponsor
sponsor
The_$hit




PostPosted: 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




PostPosted: 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




PostPosted: 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




PostPosted: 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




PostPosted: 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




PostPosted: 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.
Display posts from previous:   
   Index -> Programming, C++ -> C++ Help
View previous topic Tell A FriendPrintable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 1  [ 14 Posts ]
Jump to:   


Style:  
Search: