Hi I am trying to understand the difference between function overloading and method overloading in c++. After googling I came across this. not sure if this is correct. If wrong pls help in correction.
Method overloading and function overloading are related concepts. The term method overloading is defined as a feature which is found in various programming languages such as C++ and Java. It permits the creation of various functions with the same name. However all these functions differ from each other in terms of the type of input and the type of output of the function.
On the other hand, the term function overloading is used in object-oriented programming. It is defined as a technique in which two or more functions which have the same name are distinguished from one another using different numbers and/or types of parameters.
Source : http://www.blurtit.com/q662319.html
In C++ Method is usually used to refer a member function for class or structure while,
Function is a freestanding non member function.
How does the standard declare a Function and Method?
As per the C++ standard, A function declaration is defined in:
8.3.5 Functions [dcl.fct]
In a declaration T D where D has the form
D1 ( parameter-declaration-clause ) cv-qualifier-seqopt exception-specificationopt
and the type of the contained declarator-id in the declaration T D1 is “derived-declarator-type-listT,” the type of the declarator-id in D is “derived-declarator-type-list function of (parameter-declaration-clause) cv-qualifier-seqopt returning T”; a type of this form is a function type86).
Note that the standard further states in #4:
A cv-qualifier-seq shall only be part of the function type for a nonstatic member function
To Summarize only methods(member functions) can be const or volatile.
Overloading Criteria for Function & Method Overloading:
Thus, overloading a function and overloading a method(member function) have different criteria
Function overloading is possible if and only if:
Different number of arguments.
Different sequence of arguments or
Different arguments
While method(member function) Overloading is possible if and only if:
Different number of arguments.
Different sequence of arguments or
Different arguments or
Different cv-qualifer-seq
Note that Return type is not a criteria for overloading. Because C++ allows implementations to ignore the return value from functions/methods.
Code Examples:
Function Overloading:
void doSomething(int i);
void doSomething(std::string,int x);
Method Overloading:
class Myclass
{
public:
void doSomething(int i);
void doSomething(std::string,int x);
void doSomething(int i) const;
void doSomething(int i) volatile;
};
Above is an example of how doSomething() can be overloaded as a free standing function and as a method/member function.
They are the same thing.
However, some prefer calling methods functions that are part of a class, and functions, free functions.
//function overloading
void foo(int x);
void foo(int x, int y);
//method overloading
class A
{
void foo(int x);
void foo(int x, int y);
};
A method/function is overloaded by modifying the signature but keeping its name. The signature consists of:
name
parameter types
cv-qualifiers
So, to overload, you need only change the parameters or the cv-qualifiers. I.e. if the method is part of a class, you could also overload like so:
class A
{
void foo(int x);
void foo(int x) const;
void foo(int x, int y);
};
The prototype foo(int x) const will be called when operating on an immutable object.
On a general sense, functions return values. Methods simply do actions.
The textbook example you'll see a lot is door.open() and hood.open() (yes, we all hate the awful car -> OO analogies, but it's clear in this case). These are methods. You open the door, and there is no by-product. But, it does come down to how the door must be opened, versus how the hood is opened; they are similar enough to share the action, but differ in the detailed implementation (that'd you'd rightfully wish to hide from the user...doors open out, while hoods open up).
Functions, however, replace the original call to the function with the value returned by the function. If I understand correctly, you might show this by measuring a car.exhaust(30, 0), which returns the weight of the carbon, oxygen, and other gasses emitted in 30 seconds, travelling at 0 mph. However, a car.exhaust(30, 60) function would include details not used with a speed variable of 0, and would change the output accordingly.
There are lots of examples of function overloading, this one simply demonstrates how different parameters can affect the logic and output of the function used.
Related
From § 8.3.5.11 of ISO/IEC 14882:2011(E):
A typedef of function type may be used to declare a function but shall not be used to define a function
The standard goes on to give this example:
typedef void F();
F fv; // OK: equivalent to void fv();
F fv { } // ill-formed
void fv() { } // OK: definition of fv
What motivates this rule? It seems to limit the potential expressive usefulness of function typedefs.
Though this question is about C++, but since C++ inherits typedef and function pointer from C, so an explanation of the same question in C can be used in here. There's a formal explanation for C.
Rationale for International Standard - Programming Languages C §6.9.1 Function definitions
An argument list must be explicitly present in the declarator; it cannot be inherited from a typedef (see §6.7.5.3). That is to say, given the definition:
typedef int p(int q, int r);
the following fragment is invalid:
p funk // weird
{ return q + r ; }
Some current implementations rewrite the type of, for instance, a char parameter as if it were declared int, since the argument is known to be passed as an int in the absence of a prototype. The Standard requires, however, that the received argument be converted as if by assignment upon function entry. Type rewriting is thus no longer permissible.
It's probably mostly historical reasons. typedef was a relatively late addition to C, and was tacked onto the existing language (and caused a few problems for the parsing phase of compilers).
Also, a function definition has to define the names of the parameters, if any. A function type includes the function's return type and parameter types, but not its parameter names. For example, these:
void (int)
void (int x)
void (int y)
are three ways of writing the same function type. If you had:
typedef void func_t(int);
then this hypothetical definition:
func_t some_func { }
wouldn't define a name for its int parameter. I'm not sure how that could have been resolved in a reasonable manner. It would be possible, I suppose, but it was never done.
But the bottom line is probably just that Dennis Ritchie either didn't think it was worth the effort to define how a typedef could be used in a function definition, or he simply didn't think of it.
Let me put a few words. Consider a statement:
typedef void F(int p1, char* p2);
This statement assigns name F to a function signature void (int, char*); This is definition of an alias to the function signature. After that the statement:
F fv;
tells that there is a function fv. It has the signature that was mentioned above and it has its body somewhere. Look at the C/C++ syntax of the function definition:
retType funcName(params) { body }
There are actually 2 names used retType and funcName. None of them are the same to the name F from the initial typedef. The name F has meaning of both names. If language would allow something like:
F { body }
this will associate body with the function type. But this leads a problem:
The meaning of F would be not clear. Is it an "alias to the function signature" or is it a "name of the entry point into a code"?
Plus the syntax of the last example would be weird to millions of C/C++ programmers.
The rule is as you quoted - typedef of function type shall not be used to define a function. In the 3rd line of the example, you are trying to define a function with function type F. This is not allowed by the standard.
EDIT
As you pointed out, I try to explain more on it.
For the 3rd line, if it were legal, then you could replace F with the typedef definition:
void fv { }(). This is not a legal definition or declaration in C++.
I think the key point is that typedef is just creating an alias for simplification, and you can replace your typedef type like replacement of #define during compilation.
Is valid to have
int func();
float func(int x);
I know isn't possible overloading without templates by return type only, but this is valid correct?
Yes it is. The rule for overloading is that the parameters need to be of different type and/or number; when this is satisfied, the return type can be different for the various overloads. Given the actual arguments, the compiler can determine which overload to call.
Only overloading by return type is invalid, because the compiler cannot make a choice based on the return value; suppose you have overloads int f() and float f(), and you do
(void)f();
In this situation, there's no telling which f you intended to call. (Unless there would be some arbitrary preference for types specified in the Standard, but there isn't, and it would be hard to come up with a sensible one.)
Functions are identified by their signature.
in C++ function signature include,
name
argument type
no of arguments
order of argument
Return type of function is not consider as a part of signature.
When a function call is encountered in a program then the compiler will look for functions with that name. If multiple functions have same name(function overloading). then the compiler will check the above signature. if an exact match is not found then compiler will do some conversions and check for a match. Still not found a match it will show an error
Yes, it is correct. A function is defined by
the namespace
the name of the function
the types of arguments
But, the return type is not taken into account.
See this example :
int f(); // correct
double f(int x); // correct
void f(double y); // correct, the type is different
char f(int z); // Not correct, same signature than the 2nd function
You already got a few answer stating that it is possible, but a different question is whether it is desirable, and at this point I would advice against it in your case as it puts a burden on the user: they need to figure out what overload is picked to know what the function returns.
Note that this is not a statement that in general it is not desirable, there are many cases where having different return types for different functions make sense, for example sqrt taking a float will return a float, and if the input is a double it will produce a double, but it is natural from the syntax and the call what the return type is.
In the artificial example you provided that is not the case, or at least it is not obvious, so I'd recommend not to overload but produce different named functions.
Yes this is fine as you have different arguments for two overloads.Just for your information why compiler can't deduce from only return types which overload to call.
There's a concept called name mangling. Compiler mangles name of each function as per it's ease to call that appropriately.So if a function is,
int foo (int x );
mangled name would be something in line with foo_int. In this return type is not taken into account. So if I have two overloads like
int foo (int x );
int foo (char x);
mangled names would be something
foo_int
foo_char
respectively. But if you only choose return type for your overload resolution then it will fail as return type is not taken into account in name mangling.
In C++11 the following function declaration:
int f(void);
means the same as:
int f();
A parameter list consisting of a single unnamed parameter of non-dependent type void is equivalent to an empty parameter list.
I get the (perhaps false) impression this is an old feature, perhaps inherited from C?
Does anyone know the history or rationale behind this way to declare a function with no parameters?
In C++ they both mean the same thing.
In C f(void) is different from f(), becuse f() means "unspecified parameters" - you can legally pass anything (whether the function at receiving the data is happy about that or not is another matter).
In C++ both are the same thing.
In C, f() means that we don't know how many parameters the function takes at this point. It is unspecified parameters. And f(void) means that this function does not take any parameters.
From the C standard :
6.7.6.3 Function declarators (including prototypes)
6/ A parameter type list specifies the types of, and may declare identifiers for, the
parameters of the function.
10/ The special case of an unnamed parameter of type void as the only item in the list
specifies that the function has no parameters.
14/ An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters. The empty list in a function declarator that is not part of a definition of that function specifies that no information about the number or types of the parameters is supplied.
And like you said, in the C++ standard :
8.3.5 Functions [dcl.fct]
4/ The parameter-declaration-clause determines the arguments that can be specified, and their processing, when the function is called. [ Note: *the parameter-declaration-clause* is used to convert the arguments specified on the function call; see 5.2.2. —end note ] If the parameter-declaration-clause is empty, the function takes no arguments. A parameter list consisting of a single unnamed parameter of non-dependent type void is equivalent to an empty parameter list.
This comes to C++ from C. In C f() means unknown number and type of parameters. So in C for no parameters there is f( void ).
In C++ it's redundant: f() and f( void ) mean same thing - a function that has no parameters.
From "A History of C++" (1979− 1991 by Bjarne Stroustrup) at p11:
C with Classes introduced the notation f(void) for a function f that
takes no arguments as a contrast to f() that in C declares a function
that can take any number of arguments of any type without any type
check.
It says later, however, that soon the empty function declarator was given its obvious meaning and the new construct - kinda rendered obsolete for the time. I guess nobody has bothered removing it after (or maybe there had been already some C++ code written with it that have needed support).
In C:
This construct however rendered important role as of the standardization of the C language where function prototyping was borrowed directly from C++. In this case f(void) was useful in supporting existing C code (in which the notion f() was already reserved as to indicate a function taking unspecified number of arguments).
Before that the C language hadn't been able to attach specific types to each parameter but only functions with unspecified number of arguments and with unspecified types were declarable using the f() form.
In C++, there is no difference. However, this is inherited from C, where int f() mean "function which can take any number of arguments of any types" and int f(void); specifies functions that takes no arguments.
Edit As Angew pointed out, in C, f() means "function whose parameters are unknown at this point." It does not mean it can take any number of arguments - close to that would be f(T arg, ...), where arg is at least one named parameter before ..., which accepts at least one argument, arg (as pointed by #hvd).
From § 8.3.5.11 of ISO/IEC 14882:2011(E):
A typedef of function type may be used to declare a function but shall not be used to define a function
The standard goes on to give this example:
typedef void F();
F fv; // OK: equivalent to void fv();
F fv { } // ill-formed
void fv() { } // OK: definition of fv
What motivates this rule? It seems to limit the potential expressive usefulness of function typedefs.
Though this question is about C++, but since C++ inherits typedef and function pointer from C, so an explanation of the same question in C can be used in here. There's a formal explanation for C.
Rationale for International Standard - Programming Languages C §6.9.1 Function definitions
An argument list must be explicitly present in the declarator; it cannot be inherited from a typedef (see §6.7.5.3). That is to say, given the definition:
typedef int p(int q, int r);
the following fragment is invalid:
p funk // weird
{ return q + r ; }
Some current implementations rewrite the type of, for instance, a char parameter as if it were declared int, since the argument is known to be passed as an int in the absence of a prototype. The Standard requires, however, that the received argument be converted as if by assignment upon function entry. Type rewriting is thus no longer permissible.
It's probably mostly historical reasons. typedef was a relatively late addition to C, and was tacked onto the existing language (and caused a few problems for the parsing phase of compilers).
Also, a function definition has to define the names of the parameters, if any. A function type includes the function's return type and parameter types, but not its parameter names. For example, these:
void (int)
void (int x)
void (int y)
are three ways of writing the same function type. If you had:
typedef void func_t(int);
then this hypothetical definition:
func_t some_func { }
wouldn't define a name for its int parameter. I'm not sure how that could have been resolved in a reasonable manner. It would be possible, I suppose, but it was never done.
But the bottom line is probably just that Dennis Ritchie either didn't think it was worth the effort to define how a typedef could be used in a function definition, or he simply didn't think of it.
Let me put a few words. Consider a statement:
typedef void F(int p1, char* p2);
This statement assigns name F to a function signature void (int, char*); This is definition of an alias to the function signature. After that the statement:
F fv;
tells that there is a function fv. It has the signature that was mentioned above and it has its body somewhere. Look at the C/C++ syntax of the function definition:
retType funcName(params) { body }
There are actually 2 names used retType and funcName. None of them are the same to the name F from the initial typedef. The name F has meaning of both names. If language would allow something like:
F { body }
this will associate body with the function type. But this leads a problem:
The meaning of F would be not clear. Is it an "alias to the function signature" or is it a "name of the entry point into a code"?
Plus the syntax of the last example would be weird to millions of C/C++ programmers.
The rule is as you quoted - typedef of function type shall not be used to define a function. In the 3rd line of the example, you are trying to define a function with function type F. This is not allowed by the standard.
EDIT
As you pointed out, I try to explain more on it.
For the 3rd line, if it were legal, then you could replace F with the typedef definition:
void fv { }(). This is not a legal definition or declaration in C++.
I think the key point is that typedef is just creating an alias for simplification, and you can replace your typedef type like replacement of #define during compilation.
Is it possible to prevent overloading of user defined functions in C++? Suppose I have a function as:
void foo(int , int);
Can I prevent foo from being overloaded, and if so how? If I can, can this be extended to prevent overriding of the methods through inheritance?
In a word: no. You can't prevent an overload of foo being defined with a different signature somewhere else and you also can't prevent virtual functions from being overriden.
In the C++ world you have to give some degree of trust to people writing code that winds up in your program.
Section 13.1.1 through 13.1.3 of the standard describe the kinds of functions that can not be overloaded:
Certain function declarations cannot be overloaded:
Function declarations that differ only in the return type cannot be overloaded.
Member function declarations with the same name and the same parameter types cannot be overloaded if any of them is a static member function declaration (9.4).
Note: as specified in 8.3.5, function declarations that have equivalent parameter declarations declare the same function and therefore cannot be overloaded:
Parameter declarations that differ only in the use of equivalent typedef “types” are equivalent. A typedef is not a separate type, but only a synonym for another type (7.1.3).
Parameter declarations that differ only in a pointer * versus an array [] are equivalent. That is, the array declaration is adjusted to become a pointer declaration (8.3.5). Only the second and subsequent array dimensions are significant in parameter types (8.3.4).
Parameter declarations that differ only in that one is a function type and the other is a pointer to the same function type are equivalent. That is, the function type is adjusted to become a pointer to function type (8.3.5).
Parameter declarations that differ only in the presence or absence of const and/or volatile are equivalent. That is, the const and volatile type-specifiers for each parameter type are ignored when determining which function is being declared, defined, or called.
Two parameter declarations that differ only in their default arguments are equivalent.
Otherwise, the function can be overloaded, and there is no way to prevent that.
You cannot.
Make it a static function in a class and tell people not to modify that class?
This can be simulated by making it a struct instance:
struct foo_t {
void operator()(int, int);
} foo;
// error: redefinition of 'foo' as different kind of symbol
void foo(double, double);
or a function reference:
void foo_impl(int, int);
auto const& foo = foo_impl;
// error: redefinition of 'foo' as different kind of symbol
void foo(double, double);
Do what UncleBens said, and include in the class a constant which is an encrypted checksum of the text in the class, and a function to test it for validity. That way, nobody can change the class. Just a thought (maybe not a very good one).
As I think about it, that's pretty dumb because the class would need its own text. However, as an alternative, it could read its compiled binary code, and have a checksum for that. I'm getting out on a limb here.
The only reasonable way would be to give the function C linkage:
extern "C" void foo(int , int);
This works because with C linkage, names aren't mangled, so you can't do any overloading (which relies on encoding the types of arguments into the symbol name).
Obviously this won't extend to member functions.