473,394 Members | 1,541 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

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 2475

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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
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...
5
by: modemer | last post by:
I saw someone use the following code: void func(MyClass *& myCls) { myCls->test(); } // call func(): func(new MyClass);
5
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; }
15
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...
1
by: Iced Crow | last post by:
What is the difference between using MyClass and Me inside of inherited classes?
9
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
3
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...
4
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
2
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...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
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,...
0
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 using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.