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 11 2488
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-
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-
"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
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.)
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
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.
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)
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";
}
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
"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
"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. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: learning_C++ |
last post by:
Hi,
I compiled some code. In the function friend ostream&
operator<<(ostream& os, const complex c);
I use the later argument complex c and complex& c. I can get the same
values and there is no...
|
by: modemer |
last post by:
I saw someone use the following code:
void func(MyClass *& myCls)
{
myCls->test();
}
// call func():
func(new MyClass);
|
by: Gunnar G |
last post by:
What is the difference between the two lines in the main function?
class MyClass{ ....};
int main(){
MyClass a();
MyClass a;
}
|
by: Bart |
last post by:
Hi,
I receive an utf8 character from a database, like 田 (Japanese
Character, style: &#XXXXX).
How can I visualize the Japanese character on my application? I have found
the class...
|
by: Iced Crow |
last post by:
What is the difference between using MyClass and Me inside
of inherited classes?
| |
by: Anoj |
last post by:
Hi All,
is there any performance difference between + and & operator
while concating string litrels.
which one is better and why??
Thanx
|
by: OgaW |
last post by:
Hey anybody,
What the difference between RDRAM and DDRAM?
Is the RDRAM going to phrase out in the current market?
Any difference between a memory speed and a CPU pentium speed?
Urgently...
|
by: nembo kid |
last post by:
Was wondering why the function that overloads = operator, returns always
a const reference to the class.
Why the qualifier 'const'?
Thanks in advance
|
by: qwedster |
last post by:
Folks!
What is the difference between PostBack and Callback ( !IsPostBack and if(!IsCallback))
Like in the following Code Snippet:
protected void Page_Load(object sender, EventArgs...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers,...
| |
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
|
by: Hystou |
last post by:
Overview:
Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
|
by: agi2029 |
last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome a new...
|
by: TSSRALBI |
last post by:
Hello
I'm a network technician in training and I need your help.
I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs.
The...
| |
by: bsmnconsultancy |
last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...
| |