Thread: Weird problem with overloading

  1. #1
    Registered User
    Join Date
    Jan 2005
    Posts
    46

    Weird problem with overloading

    I just recently started getting a syntax error with my = operator and my copy constructor, but I don't even call the copy constructor in my program. here's the relevant code:

    [code]

    Code:
    //struct that contains the coefficient and exponent of each term 
    
    struct term
    {
      int co;                  //coefficient
      int exp;                //exponent
      term* link;
    };
    
    typedef term* termptr;
    
    //class that contains the head of the list
    class Polynomial
    {
      public:
        Polynomial(Polynomial& p1);
        ~Polynomial();
        Polynomial() {head = NULL;}
        void operator = (Polynomial& p1);
        Polynomial operator + (Polynomial& p1);
        termptr get_head() {return head;}
        void set_head(termptr t1) {head = t1;}
        friend istream& operator >> (istream& ins, Polynomial& p1);
        friend ostream& operator << (ostream& outs, Polynomial& p1);
      private:
        termptr head;
    };
    //I'm not gonna list the definitions because I don't think they're relevant plus some of them are quite long
    
    //here's my application file
    
    int main()
    {
      Polynomial p1, p2, result;
    
      cout << //prompt
      cin >> p1;    // the >> operator is overloaded for lists
      cout << //prompt
      cin >> p2;
      cout << endl;
      
      result = p1 + p2;
      cout << result;
    
      return 0;
    }
    okay, here's the error I keep getting:

    error: no matching function for call to 'Polynomial::Polynomial(Polynomial)'
    note: candidates are: Polynomial::Polynomial(Polynomial&)
    error: initializing argument 1 of 'void Polynomial:perator =(Polynomial&)'

    I get the error on this line in my application file: result = p1 + p2;

    I have tried everything I can think of, but I know it's something simple. help me out please
    Last edited by Strait; 02-18-2005 at 07:47 PM.

  2. #2
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    I'm not gonna list the definitions because I don't think they're relevant
    I get the error on this line in my application file: result = l1 + l2;
    I would think the definition of your operator+() function is very relevant.

  3. #3
    It's full of stars adrianxw's Avatar
    Join Date
    Aug 2001
    Posts
    4,829
    list (const list& l1);

    Remove the reference from

    void operator = (list& l1);

    without more info, can't suggest more.
    Wave upon wave of demented avengers march cheerfully out of obscurity unto the dream.

  4. #4
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    A couple of notes:
    Code:
    void operator = (list& l1);
    operator= should return a reference to the object. Otherwise you couldn't do fancy stuff like:
    result = l1 = l2;

    Unless the object being copied from can't be copied without modifiying the object (which I don't see this being the case) it should be a const reference.

    Code:
    list operator + (list& l1);
    Again unless the object being added from can't be added from without modifying the object it should be a const reference

    but I don't even call the copy constructor in my program
    Oh but you are with your operator+ The return value of operator+ returns by value. To do so it uses the copy constructor.

  5. #5
    Registered User
    Join Date
    Jan 2005
    Posts
    46
    I can't do
    Code:
    list::list(const list& l1)
    because I call get_head() in the definition

    I guess I can post my code for + and the copy constructor. the class isn't really called list, I just used that to simplify, it's actually called Polynomial and each node stores two ints instead of one. I edited the code in my first post to go with that. it's pretty long so I'll pseudocode parts of it
    Code:
    Polynomial::Polynomial (Polynomial& p1);
    {
      termptr temp, temp1;
      temp = p1.get_head();
      
      if (temp == NULL)
        return;
    
      temp1 = new term;
      temp1->co = temp->co;
      temp1->exp = temp->exp;
      temp1->link = NULL;
      head = temp1;
      temp = temp->link;
      
      for (termptr ptr = temp; ptr != NULL; ptr = ptr->link)
      {
        temp1->link = new term;
        temp1 = temp1->link;
        temp1->co = ptr->co;
        temp1->exp = ptr->exp;
      }
    }
    
    // = operator overload is the same
    
    Polynomial Polynomial::operator + (Polynomial& p1)
    {
      Polynomial temp;
      termptr temp_ptr, current, result;
      termptr cursor_a = head, cursor_b = p1.get_head();
    
      if (cursor_a->exp > cursor_b->exp)
      {
        //creates new term
        //sets new term = cursor_a
        //call temp.set_head with the new term
        //increment cursor_a to the next node
      }else if (cursor_b->exp > cursor_a->exp)
      {
        //creates new term
        //sets new term = cursor_b
        //call temp.set_head with new term
        //increment cursor_a to next node
      }else
      {
        //slightly more complicated so I'll code this
        temp_ptr = new term;
        temp_ptr->co = cursor_a->co + cursor_b->co;
        temp_ptr->exp = cursor_a->exp;
        temp.set_head(temp_ptr);
        cursor_a = cursor_a->link;
        cursor_b = cursor_b->link;
      }
    
      current = temp.get_head();
    
      while ((cursor_a != NULL) || (cursor_b != NULL))
      {
        if (cursor_a == NULL)
        {
          current->link = new term;
          current = current->link;
          current->co = cursor_b->co;
          current->exp = cursor_b->exp;
          cursor_b = cursor_b->link;
        }else if (cursor_b == NULL)
        {
          //same thing except set values in current to cursor_a and increment cursor_a
        }else if (cursor_a->exp == cursor_b->exp)
        {
          //same thing except set current->co to cursor_a->co + cursor_b->co and increment
          //both
        }else if (cursor_a->exp > cursor_b->exp)
        {
          //same as if cursor_b == NULL
        }else if (cursor_b->exp > cursor_a->exp)
        {
          //same as if cursor_a == NULL
        }
      }
      return temp;
    }
    there it is, hope that helps
    Last edited by Strait; 02-18-2005 at 07:48 PM.

  6. #6
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    Well you can make a const version of get_head
    Code:
    const termptr get_head() const {return head;}

  7. #7
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    Oh but you are with your operator+ The return value of operator+ returns by value. To do so it uses the copy constructor.
    That's what I assumed as well, but when I tried to construct an example to show that's what happens, I encountered something I didn't understand. Maybe you could tell me why the operator+ doesn't call the copy constructor below(or cause an error):

    Code:
    class Apple
    {
    public:
        int num;
    
        Apple(int a):num(a)
        {
            cout<<"constructor called"<<endl;
        }
        
        Apple(Apple& rA)
        {
            cout<<"copy constructor called"<<endl;
            num = rA.num;
        }
        
        Apple operator+(const Apple& rA)
        {
            //Apple A(num + rA.num);
            //return A;
    
            return Apple(num + rA.num);
        }
    };
    
    
    int main()
    {
        Apple A(3);
        Apple B(1);
    
        Apple C = A + B;
    
        cout<<C.num<<endl;
        
        return 0;
    }
    
    Output:
    
    constructor called
    constructor called
    constructor called
    4
    Press any key to continue
    Last edited by 7stud; 02-18-2005 at 10:26 PM.

  8. #8
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    Well there is a couple reasons. First off when I tried to compile your code I recieved the following:
    Code:
    g++ -o bt12 bt12.cpp -ansi -pedantic
    bt12.cpp: In member function `Apple Apple::operator+(const Apple&)':
    bt12.cpp:25: no matching function for call to `Apple::Apple(Apple)'
    bt12.cpp:15: candidates are: Apple::Apple(Apple&)
    bt12.cpp:9:                 Apple::Apple(int)
    bt12.cpp: In function `int main()':
    bt12.cpp:35: no matching function for call to `Apple::Apple(Apple)'
    bt12.cpp:15: candidates are: Apple::Apple(Apple&)
    bt12.cpp:9:                 Apple::Apple(int)
    Changing the copy constructor to take a const reference removed the errors and gave me the same output.

    The reason why it never called the copy constructor is because it didn't need to
    Code:
    return Apple(num + rA.num);
    At this point you created an unnamed object. Well the compiler just made that unnamed object C. Since the return value is used in the initalization of C it just removed a few steps.

    On g++ if I commented out the return and uncommented the previous two commands, the copy constructor was invoked

  9. #9
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    I don't get those errors in MS VC6. Is it mandatory that the parameter of a copy constructor be const? I realize it makes sense for it to be const, but is it required?

    At this point you created an unnamed object. Well the compiler just made that unnamed object C. Since the return value is used in the initalization of C it just removed a few steps.
    I don't understand that. Something is created within the function, and then it is passed to something outside the function. It seems to me, if it is passed by value, then the copy constructor should be called, and if it's not passed by value, then there should be an error because the return type is not a pointer or reference.
    Last edited by 7stud; 02-19-2005 at 02:34 AM.

  10. #10
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    Its not required that the copy constructor be const. However const reference has a neat little ability to take both references and values. In the above case you did not provide a copy constructor that took an Apple by value.

    What the compiler did was to modify the code slightly. Without looking at the resulting assembly code I would theorize that the compiler did one of the two following things:
    1) It passed a reference to operator+ that was used to create the return object
    or
    2) It inlined operator+ so that it became:
    Apple C(A.num + b.num);

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Weird problem
    By eurus in forum C Programming
    Replies: 8
    Last Post: 02-17-2006, 01:35 PM
  2. oops? not sure. operator overloading (possible) problem
    By w00tw00tkab00t in forum C++ Programming
    Replies: 8
    Last Post: 02-08-2006, 05:38 AM
  3. Replies: 6
    Last Post: 05-12-2005, 03:39 AM
  4. Weird class problem!
    By aker_y3k in forum C++ Programming
    Replies: 2
    Last Post: 09-25-2002, 06:12 AM
  5. function overloading problem
    By AndersSundman in forum C++ Programming
    Replies: 5
    Last Post: 02-03-2002, 03:35 PM