Thread: unable to overload functions

  1. #1
    Registered User
    Join Date
    Dec 2013
    Posts
    241

    unable to overload functions

    hey guys! I started fiddling with C++ to expend my programming knowledge , I wrote a program (which has no use other then practicing subjects I learned )

    the compiler complains that the call of overloaded "addEm" is ambiguous. I read that this probably means it can't tell which version of the function is used, yet, I don't understand how to fix it ..
    Code:
    #include <iostream>
    
    using namespace std;
    
    class cat {
        private:
            int age;
            int height;
        public:
            cat();
            cat(int a, int b);
            ~cat();
            void setAge(int a);
            void setHeight (int a);
            int getAge(void) const;
            int getHeight(void) const;
            void showDetails (void);    
    };
    
    int addEm (cat myCat);
    int addEm (const cat& myCat);    
    
    
        cat::cat(){
                cout<<"\ndefault constructor called\n";
                age=0;
                height=0;
        }
            
        cat::cat(int a, int b){
                cout<<"\nregular constructor\n";
                age=a;
                height=b;
        }
        
        cat::~cat(){
                cout<<"\ndeleting this cat\n";
        }
            
        void cat::setAge(int a) {
                age=a;
        }
            
        void cat::setHeight (int a) {
                height=a;
        }
            
        void cat::showDetails (void){
                cout<<"this cat is "<<age<<" years old and it's height is "<<height; 
        }
            
        int cat::getAge(void) const{
                return age;
        }
        
            int cat::getHeight(void) const{
                return height;
        }
    
    
    int addEm (cat myCat){
        int a,b;
        a=myCat.getHeight();
        b=myCat.getAge();
        return a+b;
    }
    
    int addEm (const cat& myCat){
        int a,b;
        a=myCat.getHeight();
        b=myCat.getAge();
        return a+b;
    }
    
    int main (void){
        
        cat blacky(3,4);
        const cat& rBlacky=blacky;
        cout<<addEm(rBlacky);
        
        cout <<"\n end the program:\n";
        return 0;
    }
    Last edited by Dave11; 05-17-2014 at 02:57 PM.

  2. #2
    Registered User
    Join Date
    Nov 2013
    Location
    Norway
    Posts
    40
    Code:
    intaddEm (cat myCat);
    int addEm (const cat& myCat);

    An ambigous call is what you think it is, and this happens because your two functions may take the same argument. Needless to say, it cant know which one is correct.
    To fix this you could just change the name of one of the functions. But considering they are identical, what you could rather do is just remove one of them. >.>
    "Derp, derp, derp" - Me

  3. #3
    Registered User
    Join Date
    Dec 2013
    Posts
    241
    Quote Originally Posted by Iceboxes View Post

    To fix this you could just change the name of one of the functions.
    but then, what is the point of overloading if I have to change the name of the function?
    and also, why is cat = const cat& ? why does it make a problem?

  4. #4
    Registered User
    Join Date
    May 2010
    Posts
    4,608
    Actually in this instance you don't need both of these functions, as already pointed out. If you look at the function body they appear to be identical. When dealing with most classes it is usually better to pass by reference, and use the const qualifier when you want to insure the parameter isn't modified.

    Jim

  5. #5
    Registered User
    Join Date
    Dec 2013
    Posts
    241
    thank you very much!
    yet, I'm mostly interested why I can't overload these functions in that way or why can't I use them as I did? let;s just say the body of the function is different ..

  6. #6
    Registered User
    Join Date
    May 2010
    Posts
    4,608
    Because in order to overload the functions the function signature must be different and the compiler must be able to tell the functions apart by these function signatures. Your functions, while they are to be different the compiler can't tell what function you want to call because the calling convention is the same. The compiler can't tell if you mean const cat& or cat, the key here is that you would pass what appears to be the same variable, an instance of a cat.

    Jim

  7. #7
    Registered User
    Join Date
    Nov 2013
    Location
    Norway
    Posts
    40
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    Purrfect explanation
    (ΦωΦ)
    "Derp, derp, derp" - Me

  8. #8
    Registered User
    Join Date
    Dec 2013
    Posts
    241
    so basically the problem is that the compiler does not differentiate between <type> and cons <type> as far as it comes to declaring arguments of a function?

    also : another questions:
    considering the two declarations <type> <fun' name> (arg1,arg2..) and the declaration <type>& <fun' name> (arg1,arg2..):
    1) is there any OTHER difference between the obvious fact that the first return a type and the other return a reference? in terms of functionallity, etc?
    2) is there any reason to return reference of a variable and not the variable itself?

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Dave11 View Post
    so basically the problem is that the compiler does not differentiate between <type> and cons <type> as far as it comes to declaring arguments of a function?
    No, it does. Remove the call to the function and you'll see that it compiles. Essentially, the compiler cannot differentiate between the functions when you call it. It doesn't know which one to call.


    Quote Originally Posted by Dave11 View Post
    1) is there any OTHER difference between the obvious fact that the first return a type and the other return a reference? in terms of functionallity, etc?
    I'm going to chance and guess no. I cannot know what it is you are after, but really, the only thing different is that that returned expression will be a reference, so the returned expression must be alive after the function ends.

    Quote Originally Posted by Dave11 View Post
    2) is there any reason to return reference of a variable and not the variable itself?
    Yes, it happens regularly with operator overloading when a class returns a reference to itself to enable chaining (i.e. a = b = c = d...).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    Registered User
    Join Date
    May 2010
    Posts
    4,608
    so basically the problem is that the compiler does not differentiate between <type> and cons <type> as far as it comes to declaring arguments of a function?
    The problem is not the function implementation but the function call. And there is a difference between const and non-const function parameters. The problem with your functions is that you when you call the function the compiler can't tell whether you want to the pass by value function or the pass by reference function because the calling signature is the same.

    Code:
    void funct(int value) {}
    void funct(int &value) {}
    
    ...
    int someValue;
    funct(someValue);  // What function should the compiler call?
    is there any OTHER difference between the obvious fact that the first return a type and the other return a reference?
    Actually the function return type is a different issue. Normally when talking about function overloading you are dealing with the parameters, not the return type. Remember it is legal to ignore the returned value so the compiler can't use the return value to determine what overloaded function to call.

    Jim

  11. #11
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,616
    1) is there any OTHER difference between the obvious fact that the first return a type and the other return a reference? in terms of functionallity, etc?
    You cannot overload based on return type. The arguments should be different in type.

    2) is there any reason to return reference of a variable and not the variable itself?
    I think it will be hard to tell the difference, but there are a few reasons to use references.

    • You avoid making copies, which is important when you want to return the same object you passed in
    • It is used in operator overloading so that you can chain them together


    The whole reason answer = a + b + c + d; works is because of operator chaining; you pass in the answer from one of the previous additions to the next one.

    Sometimes references can be wrong. If you return a reference to a local variable, the reference will become invalid.

  12. #12
    Registered User
    Join Date
    Dec 2013
    Posts
    241
    ok, so I get that the reference is just an alias to the referred variable , that why it don't know to tell the different between them when calling these specific functions. that's clear, but why didn't the "const" took effect? I mean, there is a difference between func(x) and func(const x) , right? in my example rBlacky is declared const, so, theoretically , the compiler should have called the function that declared as getting const arg?

    sorry for the stubbornness, I come from C world and C++ theories are new to me..

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    The compiler knows it's a reference by looking at its type, but the you can also create a temporary from your reference.
    The compiler cannot decide between creating a temporary and passing a reference.

    void foo(T); // <--- Can call this by making a copy of the variable
    void foo(const T&); // <-- Can call this directly.

    But both are equally "good" in the compiler's eyes, so it cannot decide which one to call.
    The thing about references are that they behave just exactly like normal variables.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,616
    Code:
    void foo (const K& x);
    void foo (K k);
    
    {
      K k;
      foo(k);
    }
    So you're the compiler. If you use the copy constructor of class K, you can call the version with parameter k. If you don't use the copy constructor, then you can call the version with parameter x. You don't necessarily know what to do, because both methods are correct and possible. That is why the call is ambiguous.

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Well, to be fair...
    Code:
    void foo (const K& x);
    void foo (K k);
     
    int main()
    {
      K k;
      copy K& rK = k;
      foo(rK);
    }
    ...using this example, the type is actually const K&, so the const K& foo would be a stronger "match". However, when the compiler looks at foo(K), it also sees that it can call K's copy constructor to make a copy and hence call foo(K). This is considered an equally "strong" match, so the compiler is cannot deduce which one to call. There are tons of "rules" for overloading which tells the compiler which overload to pick and they're quite complicated in order to make it "seem" like the compiler picks the right choice every time.

    Also, to show something off:
    Code:
    struct X 
    {
    	X() {}
    	explicit X(const X&) {}
    };
    
    void foo(X) { std::cout << "foo(X)\n"; }
    void foo(const X&) { std::cout << "foo(const X&)\n"; }
    
    int main()
    {
    	X MyX;
    	foo(MyX);
    }
    Does it compile? Does it run? If so, what does it print? The correct answer is foo(const X&). Why? Because I told the compiler: make no implicit copies of this object. Hence, the compiler discarded foo(X) and called foo(const X&). So you can clearly see here why the compiler complains it's ambiguous (remove the explicit keyword).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How to overload [][]
    By chottachatri in forum C++ Programming
    Replies: 4
    Last Post: 04-02-2008, 12:38 AM
  2. overload *
    By shuo in forum C++ Programming
    Replies: 5
    Last Post: 06-10-2007, 04:44 AM
  3. What is this overload?
    By Mortissus in forum C++ Programming
    Replies: 2
    Last Post: 07-02-2006, 10:38 PM
  4. overload
    By Unregistered in forum C++ Programming
    Replies: 3
    Last Post: 12-11-2001, 09:38 AM
  5. Overload (+) operator
    By kit in forum C++ Programming
    Replies: 8
    Last Post: 10-23-2001, 11:20 AM