469,323 Members | 1,397 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,323 developers. It's quick & easy.

What's difference between f(const MyClass & in) and f(MyClass in)

If I define the following codes:

void f(const MyClass & in) {cout << "f(const)\n";}
void f(MyClass in) {cout<<"f()\n";}

MyClass myclass;
f(myclass);

Compiler complain that it can't find the best match. Anyone could give a
detail explanation in theory? Which one is good?

Thanks
Jul 23 '05 #1
11 2082

modemer wrote:
If I define the following codes:

void f(const MyClass & in) {cout << "f(const)\n";}
void f(MyClass in) {cout<<"f()\n";}

MyClass myclass;
f(myclass);

Compiler complain that it can't find the best match. Anyone could give a detail explanation in theory? Which one is good?

Well, which function do you think *should* get called? The answer is
"nobody knows". It could call either one, that's why the compiler
complains that it doesn't have a "best" match, because both matches are
the same.

Hope this helps,
-shez-

Jul 23 '05 #2
Thanks Shezan, what you said is what I found and that's why I asked this
question here, but I want to know if there is any discussion in C++ theory
about this? I am not good at reading C++ theory book :-)

if I say, these 2 funcs have same signature, I think it's wrong because
compiler should complain like "function has been defined".
if I say, these 2 funcs is overloaded, I think it's also not correct because
they are conflicting.
so I think C++ theory could discuss this situation and explain the reason.

I am not sure if my question is clear enough.

Thanks.
"Shezan Baig" <sh************@gmail.com> wrote in message
news:11**********************@z14g2000cwz.googlegr oups.com...

modemer wrote:
If I define the following codes:

void f(const MyClass & in) {cout << "f(const)\n";}
void f(MyClass in) {cout<<"f()\n";}

MyClass myclass;
f(myclass);

Compiler complain that it can't find the best match. Anyone could

give a
detail explanation in theory? Which one is good?

Well, which function do you think *should* get called? The answer is
"nobody knows". It could call either one, that's why the compiler
complains that it doesn't have a "best" match, because both matches are
the same.

Hope this helps,
-shez-

Jul 23 '05 #3

"modemer" <me@privacy.net.invalid> wrote in message
news:d1**********@domitilla.aioe.org...
If I define the following codes:

void f(const MyClass & in) {cout << "f(const)\n";}
void f(MyClass in) {cout<<"f()\n";}

MyClass myclass;
f(myclass);

Compiler complain that it can't find the best match. Anyone could give a
detail explanation in theory? Which one is good?

Thanks

The problem is that the syntax for calling those is the same. Given the
first function, which takes a const reference, you call it by passing an
instance of the class. Given the second function, which gets its parameter
by value (making a copy as it does so), you also cll it by passing an
instance of the class. So, when the compiler sees you calling the function
by passing an instance, which function should be called?

I've never seen an instance where I need to have both versions of such a
function available. Why do you need them both?

If they do different things, then perhaps they should have different
names...?

If they do the same exact thing, then why have two of them? Pick whichever
you prefer and remove the other one.

I also wonder why the compiler allows you to declare two functions which
will later lead to an inability to pick the best match. Perhaps there is a
way to construct a call to one that will not appear to be a call to the
other? I don't know off-hand, but as I said, I simply don't do that anyway,
so the issue never comes up.

As for which is best, it may or may not matter. If you have an object for
which copying is costly, then you may prefer to pass by const reference,
since it does not make a copy. However, if you only call this function once
in a blue moon, the overall performance cost may be negligible in practice,
even if it is costly on a per-instance basis.

I tend to prefer the const reference, as a habit mostly, unless what I'm
passing is a built-in type, in which case I pass by value. But that's just
me.

-Howard


Jul 23 '05 #4
I'll just add that if the copy constructor or destructor of MyClass has
side effects, those side effects will happen with the ' void f(MyClass
in) {cout<<"f()\n";} ' version but not with the other.

This version makes a copy of the argument for the function, while the
const reference one doesn't. To illustrate:

class MyClass
{
public:
MyClass() { cout << "Constructor!\n"; }
MyClass(const MyClass& i) { cout << "Copy Constructor!\n"; }
virtual ~MyClass() { cout << "Destructor!\n"; }
};
void f1(MyClass in) {cout<<"f()\n";}
void f2(const MyClass &in) {cout<<"f()\n";}

int main()
{
MyClass a;

cout << "*** About to call f1:\n";
f1(a);
cout << "*** About to call f2:\n";
f2(a);
cout << "*** Done with call to f2\n";
}

Gives the following output:
Constructor!
*** About to call f1:
Copy Constructor!
f()
Destructor!
*** About to call f2:
f()
*** Done with call to f2
Destructor!

For this reason, moreso than the efficiency boost (though that is
always nice), I prefer the const reference if you have the choice: it
seems safer somehow.
To the original question, I also don't know why it allows both
functions. Visual C++ doesn't give an error on the second declaration,
only an "ambiguous call to an overloaded function" error at the call to
f. I also tried making the object I passed to the class const to see if
that would make it prefer the const reference, but no go.

My guess is that it's just too difficult to be sure that the call will
*always* be ambiguous.

(Other ambiguous calls can be resolved some of the time though. For
instance, the following code results in an ambigious call error:
void f(float a) {cout<<"a()\n";}
void f(double b) {cout<<"b()\n";}

int main()
{
f(1);
}
But this could of course be easily resolved by casting the argument to
a float/double.)

Jul 23 '05 #5
Howard,
I also wonder why the compiler allows you to declare two functions which
will later lead to an inability to pick the best match.
Good point! I think you clarified my question.
We know C++ is strong type checking language, but at this point, seems it
doesn't work so well.Nobody could say "const Type &" and "Type" is same
type, thus C++ standard should:

1. either rules out one of them allowed existing in same scope, i.e.
compiler should raises an error like "conflict defination" instead of
current "can't find a best match"

2. or allows both of them existing, and called with certain modifier, for
example:

void f(const MyClass & in) {cout << "f(const)\n";}
void f(MyClass in) {cout<<"f()\n";}

MyClass myclass;
f(myclass&); // this syntex will lead to call f(const MyClass & in)
f(myclass); // this syntex will lead to call f(MyClass in)

I know, probably "f(myclass&);" would be hard or impossible to be
implemented with the concerning overall of syntex parsing of the operator
"&", this is why I hope C++ theory has already analyzed this scenario.
anyone has ever seen this analysis?
"Howard" <al*****@hotmail.com> wrote in message
news:sP*********************@bgtnsc04-news.ops.worldnet.att.net...
"modemer" <me@privacy.net.invalid> wrote in message
news:d1**********@domitilla.aioe.org...
If I define the following codes:

void f(const MyClass & in) {cout << "f(const)\n";}
void f(MyClass in) {cout<<"f()\n";}

MyClass myclass;
f(myclass);

Compiler complain that it can't find the best match. Anyone could give a
detail explanation in theory? Which one is good?

Thanks

The problem is that the syntax for calling those is the same. Given the
first function, which takes a const reference, you call it by passing an
instance of the class. Given the second function, which gets its

parameter by value (making a copy as it does so), you also cll it by passing an
instance of the class. So, when the compiler sees you calling the function by passing an instance, which function should be called?

I've never seen an instance where I need to have both versions of such a
function available. Why do you need them both?

If they do different things, then perhaps they should have different
names...?

If they do the same exact thing, then why have two of them? Pick whichever you prefer and remove the other one.

I also wonder why the compiler allows you to declare two functions which
will later lead to an inability to pick the best match. Perhaps there is a way to construct a call to one that will not appear to be a call to the
other? I don't know off-hand, but as I said, I simply don't do that anyway, so the issue never comes up.

As for which is best, it may or may not matter. If you have an object for
which copying is costly, then you may prefer to pass by const reference,
since it does not make a copy. However, if you only call this function once in a blue moon, the overall performance cost may be negligible in practice, even if it is costly on a per-instance basis.

I tend to prefer the const reference, as a habit mostly, unless what I'm
passing is a built-in type, in which case I pass by value. But that's just me.

-Howard

Jul 23 '05 #6
In article <d1**********@domitilla.aioe.org>,
"modemer" <me@privacy.net.invalid> wrote:
Howard,
I also wonder why the compiler allows you to declare two functions which
will later lead to an inability to pick the best match.


Good point! I think you clarified my question.


The compiler allows it because, if you don't use the function then it
doesn't matter that there would be a conflict.
Jul 23 '05 #7
Daniel T. wrote:
In article <d1**********@domitilla.aioe.org>,
"modemer" <me@privacy.net.invalid> wrote:

Howard,

I also wonder why the compiler allows you to declare two functions which
will later lead to an inability to pick the best match.


Good point! I think you clarified my question.

The compiler allows it because, if you don't use the function then it
doesn't matter that there would be a conflict.


And you can "use" that function without ambiguity. In particular, you
can assign its address to a pointer to member function with a suitable type.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 23 '05 #8
Ah, and the mystery is solved!

Here is code to illustrate what Pete is saying:

class MyClass
{
public:
MyClass() { cout << " Constructor!\n"; }
MyClass(const MyClass& i) { cout << " Copy
Constructor!\n"; }
virtual ~MyClass() { cout << " Destructor!\n"; }

};

void f(MyClass in) {cout<<" f(MyClass)\n";}
void f(const MyClass &in) {cout<<" f(const MyClass&)\n";}

typedef void (*f1p_t)(MyClass);
typedef void (*f2p_t)(const MyClass&);

int main()
{
MyClass a;

f1p_t f1p = f;
f2p_t f2p = f;

cout << " * About to call f(MyClass):\n";
f1p(a);
cout << " * About to call f(const MyClass&):\n";
f2p(a);
cout << "Done with calls; back in main\n";
}

Jul 23 '05 #9
Howard wrote:
I also wonder why the compiler allows you to declare two functions which
will later lead to an inability to pick the best match.
Because these functions can be used in other contexts, where the
compiler will not be faced with the problem of picking the best match.
Perhaps there is a
way to construct a call to one that will not appear to be a call to the
other?


Yes.

MyClass in;
void (*p)(MyClass) = &f;
(*p)(in);

The code above "forcefully" picks and calls the second version of the
function.

--
Best regards,
Andrey Tarasevich
Jul 23 '05 #10
"modemer" <me@privacy.net.invalid> wrote:
If I define the following codes:

void f(const MyClass & in) {cout << "f(const)\n";}
void f(MyClass in) {cout<<"f()\n";}

MyClass myclass;
f(myclass);

Compiler complain that it can't find the best match. Anyone
could give a detail explanation in theory? Which one is good?


The same error also exists if myclass is declared const:
/////////////////////
void f(const MyClass & in) { cout << "f(const reference)\n"; }
void f(MyClass in) { cout << "f(value)\n"; }

const MyClass myclass;
f(myclass);
//
If "f(const reference)" is changed to "f(reference)", the error also
occurs!:
/////////////////////
void f(MyClass & in) { cout << "f(reference)\n"; }
void f(MyClass in) { cout << "f(value)\n"; }

MyClass myclass;
f(myclass);
//
However, the error does not occur -- and f(value) is called -- if myclass is
const:
/////////////////////
void f(MyClass & in) { cout << "f(reference)\n"; }
void f(MyClass in) { cout << "f(value)\n"; }

const MyClass myclass;
f(myclass);
//
The error will occur (twice) no-matter the constness of myclass if all three
functions are defined:
/////////////////////
void f(MyClass & in) { cout << "f(reference)\n"; }
void f(const MyClass & in) { cout << "f(const reference)\n"; }
void f(MyClass in) { cout << "f(value)\n"; }

const MyClass constmyclass;
MyClass myclass;
f(constmyclass);
f(myclass)
//
However, the compiler error doesn't exist if f(value) isn't defined:
/////////////////////
void f(MyClass & in) { cout << "f(reference)\n"; }
void f(const MyClass & in) { cout << "f(const reference)\n"; }

/*const*/ MyClass myclass;
f(myclass);
//

In the previous example though, when the program runs, f(reference) is
called if myclass is non-const and f(const reference) is called if myclass
is const.
The situations are exactly the same if "f(value)" is replaced with "f(const
value)". However, if both "f(value)" and "f(const value)" exist, the
compiler says that f(value) has already been defined (or "f(const value)",
depending on which is defined first).
Other responses in the thread indicate that it is possible to explicitly
specify which function to call. To me that seems like bending-over-backward
to deal with a possible shortcoming of the language and/or compiler.

Yes maybe the compiler should be able to handle the ambiguities better.
However, why differentiate functionality based only on switching the
non-const/const and/or value/reference nature of a function's parameter(s)?
(And if that is found to be useful, would it be called "ambiguous
polymorphishm"?)

crichmon
Jul 23 '05 #11

"crichmon" <cr******@gmail.com> wrote in message
news:7T*****************@newsread2.news.atl.earthl ink.net...
"modemer" <me@privacy.net.invalid> wrote:
If I define the following codes:

void f(const MyClass & in) {cout << "f(const)\n";}
void f(MyClass in) {cout<<"f()\n";}

MyClass myclass;
f(myclass);

Compiler complain that it can't find the best match. Anyone
could give a detail explanation in theory? Which one is good?
The same error also exists if myclass is declared const:
/////////////////////
void f(const MyClass & in) { cout << "f(const reference)\n"; }
void f(MyClass in) { cout << "f(value)\n"; }

const MyClass myclass;
f(myclass);
//
If "f(const reference)" is changed to "f(reference)", the error also
occurs!:
/////////////////////
void f(MyClass & in) { cout << "f(reference)\n"; }
void f(MyClass in) { cout << "f(value)\n"; }

MyClass myclass;
f(myclass);
//
However, the error does not occur -- and f(value) is called -- if myclass

is const:
/////////////////////
void f(MyClass & in) { cout << "f(reference)\n"; }
void f(MyClass in) { cout << "f(value)\n"; }

const MyClass myclass;
f(myclass);
//
The error will occur (twice) no-matter the constness of myclass if all three functions are defined:
/////////////////////
void f(MyClass & in) { cout << "f(reference)\n"; }
void f(const MyClass & in) { cout << "f(const reference)\n"; }
void f(MyClass in) { cout << "f(value)\n"; }

const MyClass constmyclass;
MyClass myclass;
f(constmyclass);
f(myclass)
//
However, the compiler error doesn't exist if f(value) isn't defined:
/////////////////////
void f(MyClass & in) { cout << "f(reference)\n"; }
void f(const MyClass & in) { cout << "f(const reference)\n"; }

/*const*/ MyClass myclass;
f(myclass);
//

In the previous example though, when the program runs, f(reference) is
called if myclass is non-const and f(const reference) is called if myclass
is const.
The situations are exactly the same if "f(value)" is replaced with "f(const value)". However, if both "f(value)" and "f(const value)" exist, the
compiler says that f(value) has already been defined (or "f(const value)",
depending on which is defined first).
Other responses in the thread indicate that it is possible to explicitly
specify which function to call. To me that seems like bending-over-backward to deal with a possible shortcoming of the language and/or compiler.

Yes maybe the compiler should be able to handle the ambiguities better.
However, why differentiate functionality based only on switching the
non-const/const and/or value/reference nature of a function's parameter(s)? (And if that is found to be useful, would it be called "ambiguous
polymorphishm"?)

crichmon


Thanks crichmon's analysis in such depth, so far looks like nobody has ever
found any C++ works analyzing "ambiguous" in detail and found the reason why
C++ allows these "ambiguous" existing, rather than just like trying to
cover all of type checking.
Jul 23 '05 #12

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by learning_C++ | last post: by
5 posts views Thread by modemer | last post: by
5 posts views Thread by Gunnar G | last post: by
15 posts views Thread by Bart | last post: by
4 posts views Thread by nembo kid | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by zhoujie | last post: by
reply views Thread by Gurmeet2796 | last post: by
reply views Thread by mdpf | last post: by
reply views Thread by harlem98 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.