Operator overloading and *this

Discussion in 'C++' started by y-man, Mar 21, 2007.

  1. y-man

    y-man Guest

    Hi,

    I am trying to get an overloaded operator to work inside the class it
    works on. The situation is something like this:


    main.cc:
    #include "object.hh"
    #include "somefile.hh"
    object obj, obj2 ;

    obj2 = obj.bla(25) ;



    object.hh:

    class object {
    public:
    object() {} ;

    void set_a(double num) {
    a = num ;
    }

    double get_a( void ) {
    return a;
    }

    bla(double num) {
    return (*this) + num
    }
    private:
    double a;

    } ;


    somefile.hh:
    #include "object.hh"
    object operator+ (double, object)

    somefile.cc:

    object operator+ (double a, object obj) {
    obj.set_a(obj.get_a + a) ;
    }

    When I compile, I find out that the object does not know that the
    operator exists. Is there a way to make this work correctly?
     
    y-man, Mar 21, 2007
    #1
    1. Advertising

  2. y-man

    mlimber Guest

    On Mar 21, 11:48 am, "y-man" <> wrote:
    > Hi,
    >
    > I am trying to get an overloaded operator to work inside the class it
    > works on. The situation is something like this:
    >
    > main.cc:
    > #include "object.hh"
    > #include "somefile.hh"
    > object obj, obj2 ;
    >
    > obj2 = obj.bla(25) ;
    >
    > object.hh:
    >
    > class object {
    > public:
    > object() {} ;
    >
    > void set_a(double num) {
    > a = num ;
    >
    > }
    >
    > double get_a( void ) {
    > return a;
    >
    > }
    >
    > bla(double num) {
    > return (*this) + num}
    >
    > private:
    > double a;
    >
    > } ;
    >
    > somefile.hh:
    > #include "object.hh"
    > object operator+ (double, object)
    >
    > somefile.cc:
    >
    > object operator+ (double a, object obj) {
    > obj.set_a(obj.get_a + a) ;
    >
    > }
    >
    > When I compile, I find out that the object does not know that the
    > operator exists. Is there a way to make this work correctly?


    Include somefile.hh in object.hh before the definition of
    object::bla(), add to it an operator that takes an object and a double
    (in that order), and fix your syntax errors. BTW, you probably want
    the parameter to your function to be "const object&". See also this
    FAQ on posting code that doesn't work:

    http://www.parashift.com/c -faq-lite/how-to-post.html#faq-5.8

    Cheers! --M
     
    mlimber, Mar 21, 2007
    #2
    1. Advertising

  3. y-man

    blangela Guest

    On Mar 21, 8:48 am, "y-man" <> wrote:
    > Hi,
    >
    > I am trying to get an overloaded operator to work inside the class it
    > works on. The situation is something like this:
    >
    > main.cc:
    > #include "object.hh"
    > #include "somefile.hh"
    > object obj, obj2 ;
    >
    > obj2 = obj.bla(25) ;
    >
    > object.hh:
    >
    > class object {
    > public:
    > object() {} ;
    >
    > void set_a(double num) {
    > a = num ;
    >
    > }
    >
    > double get_a( void ) {
    > return a;
    >
    > }
    >
    > bla(double num) {
    > return (*this) + num}
    >
    > private:
    > double a;
    >
    > } ;
    >
    > somefile.hh:
    > #include "object.hh"
    > object operator+ (double, object)
    >
    > somefile.cc:
    >
    > object operator+ (double a, object obj) {
    > obj.set_a(obj.get_a + a) ;
    >
    > }
    >
    > When I compile, I find out that the object does not know that the
    > operator exists. Is there a way to make this work correctly?


    Here is something I threw together for my class as an introduction to
    operator overloading. It may be of benifit to you (please note that I
    will use the term "method" instead of "member function" at some points
    throughout the description below):

    Let us start with the assumption that we have created a class called
    BigInt which will represent an integer value internally as a string of
    digits. Therefore the number 123456789012345 would be represented
    internally within a BigInt object as the string "123456789012345".
    The advantage BigInt class has over built-in types like "long" and
    "int" is that the BigInt class is able to represent integers of almost
    limitless precision (limited only by the amount of memory available to
    the process running our application).

    If we supply BigInt class with a method to sum two BigInt objects, we
    might write some code that looks like this:

    BigInt A,B; // Instantiate 2 BigInt objects

    .... // A and B are assigned values here

    A.Add(B); // The Add method will sum A and B.

    The implementation for the Add() method might look like this:

    BigInt & BigInt::Add( const BigInt & RHS)
    {
    /* In here is the code to sum the two BigInt objects (the BigInt
    object pointed to by the "this" pointer and the RHS BigInt object) */
    }

    There are at two problems with the solution described above. First,
    when we look at the line of code that invokes the Add method, we are
    not certain whether A is being added to B or if B is being added to A.
    The second problem is that the syntax used above means that our BigInt
    class is NOT a first rate data type. Instead, we would like to be
    able to write the following code:

    A += B; // Sum B into A

    If we were able to write our code in the manner shown in the statement
    above, we would be well on our way to making the BigInt class into a
    first rate data type!

    In order to write the code in the manner shown above, we must provide
    the compiler with a method (aka member function) or a global function
    that it may use to overload the "+=" operator. The compiler will
    cause this method or global function to be invoked whenever it
    encounters the "+=" operator with a BigInt object to the left of the
    operator and a BigInt object to the right of the operator. Supplying
    the C++ compiler with such a method or global function is called
    "overloading an operator".

    The method used to overload the "+=" operator discussed above would
    look like this:

    BigInt & BigInt::eek:perator += ( const BigInt & RHS)
    {
    /* Here we provide the code to sum together the two BigInt objects
    (the BigInt object pointed to by the "this" pointer and the RHS BigInt
    object) */
    }

    It is important to understand that the implementation of the method
    above would be exactly the same as the implementation would have been
    for the Add() method discussed above - except that the method would be
    called "operator +=" instead of "Add".

    We can invoke the "operator +=" method in exactly the same manner as
    we invoked the "Add" method above:

    A.operator +=(B); // Sum B into A

    Not that we would be likely do so! Calling our method "operator +="
    instead of "Add" causes the compiler to recognize that the "+="
    operator is now overloaded. Now, anytime the compiler encounters the
    "+=" operator with a BigInt operand on the left hand side of the
    operator and a BigInt operand on the right hand side of the operator,
    the compiler will invoke the "operator +=" method . Therefore, instead
    of invoking the method as shown in the program statement above, we
    should invoke it in the following manner:

    A += B; // Invokes the same method as: A.operator +=(B);

    Much better don't you agree! Now our BigInt class is a first rate
    data type!

    But what if we have the following program statements:

    BigInt A; // Instantiate a BigInt object
    long L = 10; // Instantiate a long object
    .... // A is assigned a value here
    A += L ; // What happens here?

    Will the above statement cause the "operator +=" method we discussed
    above to be invoked? Yes, but only if we provide the compiler with a
    way to convert L (which is a long) into a BigInt. In order to do
    this, we would need to provide the compiler with a conversion
    constructor that looks something like this:

    BigInt::BigInt(const long & L_value)
    {
    /* Convert the long L_value into a BigInt and assign it to the BigInt
    object pointed to by the "this" pointer. */
    }

    If we do not provide such a conversion constructor, the program
    statement:

    A += L; // What happens here?

    will cause a compile error unless we overload the "+=" operator a
    second time by providing the compiler the implementation for the
    following method:

    BigInt & BigInt::eek:perator += ( const long & RHS)
    {
    /* Here we provide the code to sum together the BigInt object and the
    long object (the BigInt object pointed to by the "this" pointer and
    the RHS long object) */
    }

    And if we wanted to code the following program statements as well:

    BigInt A; // Instantiate a BigInt object
    double d = 10.0; // Instantiate a double object
    .... // A is assigned a value here
    A += d ;

    Again, if we do not provide an appropriate conversion constructor, we
    would need to overload the "+=" operator a third time and provide the
    compiler with the implementation for the following method:

    BigInt & BigInt::eek:perator += ( const double & RHS)
    {
    /* Here we provide the code to sum together the BigInt object and the
    double object (the BigInt object pointed to by the "this" pointer and
    the RHS double object) */
    }

    Hopefully you are starting to see a pattern here. Now what if we want
    to code the following program statements:

    BigInt A; // Instantiate a BigInt objects
    double d = 10.0; // Instantiate a double object
    .... // A is assigned a value here
    d += A; // a double value to the left of the +=
    operator and
    // a BigInt value to the right of the +=
    operator

    You ask, what is the difference between the code segment above and the
    code segment previous to it? The difference is, that now, the double
    value is on the left hand side of the "+=" operator, where as in the
    previous example the double value was on the right hand side of the
    operator. Will the following method provide the required solution?

    BigInt & BigInt::eek:perator += ( const BigInt & RHS)
    {
    /* Here we provide the code to sum together the double object and the
    BigInt object (the double object pointed to by the "this" pointer and
    the RHS BigInt object) */
    }

    No! Why? Because a method of the BigInt class must be invoked with a
    BigInt object and not with a double object. Neither can we add a new
    method to the "double" class (programmers cannot augment the built-in
    classes). Therefore, in this case, we must overload the += operator as
    a global function. The following global function will work:

    double & operator += (double & LHS, const BigInt & RHS)
    {
    /* Here we provide the code to sum together the double object and
    the BigInt object (the LHS double object and the RHS BigInt object) */
    }

    Since the above function will need to access the private members of
    the RHS BigInt object in order to add the two objects together, the
    BigInt class will need to extend friendship to the above function. We
    say therefore that the above function needs to be a "friend
    function".

    Whether we use a method or a global function to overload an operator
    usually depends on the situation. Often either could actually be
    used, but one might be more preferable. Generally we prefer to use a
    global function over a method when overloading an operator, simply to
    limit the number of methods that have access to the private data of
    our class. If we overload an operator as a method, it is usually
    because the overloaded operator requires access to one or more of the
    private members of the class.

    This completes your introduction to operator overloading.

    I hope that clears up a few points.

    Bob L.
     
    blangela, Mar 21, 2007
    #3
  4. y-man

    y-man Guest

    Thanks to botrh of you! I have made it working. Sorry for posting in a
    bad way and thanks for the manual.
     
    y-man, Mar 26, 2007
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John Smith
    Replies:
    2
    Views:
    423
    Ivan Vecerina
    Oct 6, 2004
  2. Replies:
    11
    Views:
    735
    James Kanze
    May 16, 2007
  3. hurcan solter
    Replies:
    3
    Views:
    733
    Cholo Lennon
    Aug 29, 2007
  4. Replies:
    11
    Views:
    562
  5. Replies:
    2
    Views:
    312
Loading...

Share This Page