I've come across some C++ code that looks like this (simplified for this post):
(Here's the function prototype located in someCode.hpp)
void someFunction(const double & a, double & b, const double c = 0, const double * d = 0);
(Here's the first line of the function body located in someCode.cpp that #include's someCode.hpp)
void someFunction(const double & a, double & b, const double c, const double * d);
Can I legally call someFunction using:
someFunction(*ptr1, *ptr2);
and/or
someFunction(*ptr1, *ptr2, val1, &val2);
where the variables ptr1, ptr2, val, and val2 have been defined appropriately and val1 and val2 do not equal zero? Why or why not?
And if it is legal, is this syntax preferred vs overloading a function to account for the optional parameters?
Yes, this is legal, this is called default arguments. I would say it's preferred to overloading due to involving less code, yes.
Regarding your comment about const, that doesn't apply to the default value itself, it applies to the argument. If you have an argument of type const char* fruit = "apple", that doesn't mean it has to be called with a character pointer whose value is the same as the address of the "apple" string literal (which is good, since that would be hard to guarantee). It just means that it has to be called with a pointer to constant characters, and tells you that the function being called doesn't need to write to that memory, it is only read from.
Yes, the parameters are optional and when you don't pass them, the given default values will be used.
It has some advantages and disadvantages to use default parameter values instead of overloading. The advantage is less typing in both interface and implementation part. But the disadvantage is that the default value is a part of interface with all its consequences. Then when you change the default value, you for example need to recompile a lot of code instead of a single file when using overloading.
I personally prefer default parameters.
I'd like to expand a bit on whether Default Parameters are preferred over overloading.
Usually they are for all the reasons given in the other answers, most notably less boilerplate code.
There are also valid reasons that make overloading a better alternative in some situations:
Default values are part of the interface, changes might break clients (as #Juraj already noted)
Additionally Overloads make it easier to add additional (combinations of) parameters, without breaking the (binary) interface.
Overloads are resolved at compile time, which can give the compiler better optimization (esp inlining) possibilities. e.g. if you have something like this:
void foo(Something* param = 0) {
if (param == 0) {
simpleAlgorithm();
} else {
complexAlgorithm(param);
}
}
It might be better to use overloads.
Can I legally call someFunction using:
someFunction(*ptr1, *ptr2);
Absolutely! Yes, the other 2 variables that the function accepts would have default values you have set in the header file which is zero for both the arguments.
But if you do supply the 3rd and the 4th argument to the function, then those values are considered instead of the default values.
Related
The Google C++ Style Guide draws a clear distinction (strictly followed by cpplint.py) between input parameters(→ const ref, value) and input-output or output parameters (→ non const pointers) :
Parameters to C/C++ functions are either input to the function, output
from the function, or both. Input parameters are usually values or
const references, while output and input/output parameters will be
non-const pointers.
And further :
In fact it is a very strong convention in Google code that input arguments are values or const references while output arguments are pointers.
But I can't figure out why input/output arguments (I leave output arguments aside) should not be passed by reference. On stackoverflow there are plenty of topics related to this question : e.g. here, the accepted answer clearly say that
it's mostly about style
but that if
you want to be able to pass null, you must use a pointer
So, what's the point to always demand a pointer if I want to avoid the pointer to be null ? Why only use references for input arguments ?
The reason for demanding that output parameters are passed as pointers is simple:
It makes it clear at the call site that the argument is potentially going to be mutated:
foo(x, y); // x and y won't be mutated
bar(x, &y); // y may be mutated
When a code base evolves and undergoes incremental changes that are reviewed by people who may not know the entire context all the time, it is important to be able to understand the context and impact of a change as quickly as possible. So with this style rule, it is immediately clear whether a change introduces a mutation.
The point they are making (which I disagree with) is that say I have some function
void foo(int a, Bar* b);
If the b argument is optional, or it is unnecessary sometimes, you can call the function like so
foo(5, nullptr);
If the function was declared as
void foo(int a, Bar& b);
Then there is no way to not pass in a Bar.
This point (emphasis mine) is completely opinion-based and up to the developer's discretion.
In fact it is a very strong convention in Google code that input arguments are values or const references while output arguments are pointers.
If I intend for b to be an output parameter, either of the following are perfectly valid and reasonable.
void foo(int a, Bar* b); // The version Google suggests
void foo(int a, Bar& b); // Reference version, also perfectly fine.
You're first question: "So, what's the point to always demand a pointer if I want to avoid the pointer to be null?"
Using a pointer announces to the caller that their variable may be modified. If I am calling foo(bar), is bar going to be modified? If I am calling foo(&bar) it's clear that the value of bar may be modified.
There are many examples of functions which take in a null indicating an optional output parameter (off the top of my head time is a good example.)
Your second question: "Why only use references for input arguments?"
Working with a reference parameter is easier than working with a pointer argument.
int foo(const int* input){
int return = *input;
while(*input < 100){
return *= *input;
(*input)++;
}
}
This code rewritten with a reference looks like:
int foo(const int& input){
int return = input;
while(input < 100){
return *= input;
input++;
}
}
You can see that using a const int& input simplifies the code.
They likely use it for consistency because they use output parameters both as references to existing memory (they're modifying previously initialized variables) and as actual outputs (the output arguments are assumed to be assigned by the function itself). For consistency, they use it as a way to more clearly indicate inputs vs. outputs.
If you never need a function/method to assign the memory of the output parameter, like returning a pointer from a lookup or allocating memory itself and returning it through a pointer, use references. If you need to do that but don't care about using pointers to act as an indication of whether a parameter is input or output, use references for output parameters when appropriate. There's no absolute requirement to use pointers in all cases unless the requirements of that function/method itself requires it.
My employer company has an API package & I am asked to create a test for QA using a certain function of a class. The function is something like this:
void func(int a, int b, int c, int d, int e);
where b & d are default parameters. The types are obviously not int, I have created them here for understanding purpose. Currently I can use that function by passing NULL for the default args. But I was thinking in the case of above function func, if the default value for b & d was non-zero say 1 & the user did not know this & if he used NULL (which is = 0) then a different result would be arrived.
So I would like to know how should I create such functions that have default args between non-default ones & I should not be needed to pass anything for that arg i.e.
func(23, , 34, , 45);
Currently VS2010 is giving me compile error for similar implementation for our company's API call.
I hope I made the question pretty clear to understand.
I tried searching similar question elsewhere too but could not find solution for my query.
Thank You.
You can't do that, you have to put all non-optional parameters first, followed by optional parameters after.
You can read a bit more about optional parameters here. Microsoft says:
Default arguments are used only in function calls where trailing arguments are omitted — they must be the last argument(s). Therefore, the following code is illegal:
int print( double dvalue = 0.0, int prec );
void func(int a, int c, int e)
{
int default_b = 1;
int default_d = 1;
func(a, default_b, c, default_d, e);
}
Otherwise you simply can't, as there is no named parameters in C++.
(Though another solution would be to use boost::bind or a similar functor).
If you can modify the original function, you can simply use default value at the condition the defaulted parameter are at the end :
void func(int a, int c, int e, int b = 1, int d = 1);
How do you expect the compiler to know that you mean to pass a,c and e and not some other triplet? In a function declaration all parameters after a parameter with default value should have default values. So you can never have default b and d - whenever you pass only three parameters to this function it would mean you want to use the default values for the last 2 parameters and these are d and e. Move your optional parameters as last in the function.
There is no direct way to achieve what you are looking for.
The first alternative would be the use of boost::optional<T> for the parameters.
Another alternative might be named parameters, as implemented in the Boost Parameter Library.
If you think that this might be something for you and you want further elaboration on how these could be used for your use case, let me know and I'll edit this answer.
There is a boost library for this boost::parameter http://www.boost.org/doc/libs/1_53_0/libs/parameter/doc/html/index.html
It supports named parameters in arbitrary order with default values for non used parameters.
Hi i have a confusion or to say more i need to understand something. I have a procedure and another overloaded procedure of same.
string conct (string a, string b) {
string str = conct(a, b, "string");
return str;
}
string conct (string a, string b, const char* c) {
// do the processing;
return concatenated_string;
}
is it possible that instead of having two overloaded functions, if i make c in the overloaded function as default argument. So that even if someone passes only two arguments, i can just have one function to handle that case.
But my main concern comes in the third argument which is currently const char* c. So if i make it to something like const char* c = "string", would it be correct way to handle the case of removing overloading with one function with default argument.
I saw the post here but that seems to be focused on compilation and not the confusion i have.
Yes, you can replace your overloaded functions with one function and a default argument:
string conct (string a, string b, const char* c = "string") {
// do the processing;
return concatenated_string;
}
When you overload functions the compiler generates code for each function, probably resulting in larger code size.
If an overload just acts as a thin wrapper as in your case then the optimizer may eliminate the extra work.
default arguments get set at the caller's location, rather than inside the function, so default arguments must be publicly visible, and changing them requires recompiling all callers. With an overload like yours the psuedo-default argument becomes a hidden detail.
default values can be used in function prototypes but if we want to default middle argument then we'll have to default all values to its right...
On the other hand overloading a function can be done for all possible argument combinations also default value needs not to be placed on function call stack and thus less work for the compiler...
void f() means that f returns nothing. If void returns nothing, then why we use it? What is the main purpose of void?
When C was invented the convention was that, if you didn't specify the return type, the compiler automatically inferred that you wanted to return an int (and the same holds for parameters).
But often you write functions that do stuff and don't need to return anything (think e.g. about a function that just prints something on the screen); for this reason, it was decided that, to specify that you don't want to return anything at all, you have to use the void keyword as "return type".
Keep in mind that void serves also other purposes; in particular:
if you specify it as the list of parameters to a functions, it means that the function takes no parameters; this was needed in C, because a function declaration without parameters meant to the compiler that the parameter list was simply left unspecified. In C++ this is no longer needed, since an empty parameters list means that no parameter is allowed for the function;
void also has an important role in pointers; void * (and its variations) means "pointer to something left unspecified". This is useful if you have to write functions that must store/pass pointers around without actually using them (only at the end, to actually use the pointer, a cast to the appropriate type is needed).
also, a cast to (void) is often used to mark a value as deliberately unused, suppressing compiler warnings.
int somefunction(int a, int b, int c)
{
(void)c; // c is reserved for future usage, kill the "unused parameter" warning
return a+b;
}
This question has to do with the history of the language: C++ borrowed from C, and C used to implicitly type everything untyped as int (as it turned out, it was a horrible idea). This included functions that were intended as procedures (recall that the difference between functions and procedures is that function invocations are expressions, while procedure invocations are statements). If I recall it correctly from reading the early C books, programmers used to patch this shortcoming with a #define:
#define void int
This convention has later been adopted in the C standard, and the void keyword has been introduced to denote functions that are intended as procedures. This was very helpful, because the compiler could now check if your code is using a return value from a function that wasn't intended to return anything, and to warn you about functions that should return but let the control run off the end instead.
In imperative programming languages such as C, C++, Java, etc., functions and methods of type void are used for their side effects. They do not produce a meaningful value to return, but they influence the program state in one of many possible ways. E.g., the exit function in C returns no value, but it has the side effect of aborting the application. Another example, a C++ class may have a void method that changes the value of its instance variables.
void() means return nothing.
void doesn't mean nothing. void is a type to represent nothing. That is a subtle difference : the representation is still required, even though it represents nothing.
This type is used as function's return type which returns nothing. This is also used to represent generic data, when it is used as void*. So it sounds amusing that while void represents nothing, void* represents everything!
Because sometimes you dont need a return value. That's why we use it.
If you didn't have void, how would you tell the compiler that a function doesn't return a value?
Cause consider some situations where you may have to do some calculation on global variables and put results in global variable or you want to print something depending on arguments , etc.. In these situations you can use the method which dont return value.. i.e.. void
Here's an example function:
struct SVeryBigStruct
{
// a lot of data here
};
SVeryBigStruct foo()
{
SVeryBigStruct bar;
// calculate something here
return bar;
}
And now here's another function:
void foo2(SVeryBigStruct& bar) // or SVeryBigStruct* pBar
{
bar.member1 = ...
bar.member2 = ...
}
The second function is faster, it doesn't have to copy whole struct.
probably to tell the compiler " you dont need to push and pop all cpu-registers!"
Sometimes it can be used to print something, rather than to return it. See http://en.wikipedia.org/wiki/Mutator_method#C_example for examples
Functions are not required to return a value. To tell the compiler that a function does not return a value, a return type of void is used.
This C++ question seems to be pretty basic and general but still I want someone to answer.
1) What is the difference between a function with variable-length argument and an overloaded function?
2) Will we have problems if we have a function with variable-length argument and another same name function with similar arguments?
2) Do you mean the following?
int mul(int a, int b);
int mul(int n, ...);
Let's assume the first multiplies 2 integers. The second multiplies n integers passed by var-args. Called with f(1, 2) will not be ambiguous, because an argument passed through "the ellipsis" is associated with the highest possible cost. Passing an argument to a parameter of the same type however is associated with the lowest possible cost. So this very call will surely be resolved to the first function :)
Notice that overload resolution only compares argument to parameter conversions for the same position. It will fail hard if either function for some parameter pair has a winner. For example
int mul(int a, int b);
int mul(double a, ...);
Imagine the first multiplies two integers, and the second multiplies a list of doubles that is terminated by a 0.0. This overload set is flawed and will be ambiguous when called by
mul(3.14, 0.0);
This is because the second function wins for the first argument, but the first function wins for the second argument. It doesn't matter that the conversion cost for the second argument is higher for the second function than the cost of the first argument for the first function. Once such a "cross" winner situation is determined, the call for such two candidates is ambiguous.
1) Well an overloaded function will require a HELL of a lot of different prototypes and implementations. It will also be type safe.
2) Yes this will cause you problems as the compiler will not know which function it needs to call. It may or may not warn about this. If it doesn't you may well end up with hard to find bugs.
An overloaded function can have completely different parameter types, including none, with the correct one being picked depending on the parameter types.
A variable-length argument requires at least one parameter to be present. You also need some mechanism to "predict" the type of the next parameter (as you have to state it in va_arg()), and it has to be a basic type (i.e., integer, floating point, or pointer). Common techniques here are "format strings" (as in printf(), scanf()), or "tag lists" (every odd element in the parameter list being an enum telling the type of the following even element, with a zero enum to mark the end of the parameter list).
Generally speaking, overloading is the C++ way to go. If you end up really needing something akin to variable-length argument lists in C++, for example for conveniently chaining arguments of various number and type, consider how C++ streams work (those concatenated "<<" and ">>"s):
class MyClass {
public:
MyClass & operator<<( int i )
{
// do something with integer
return *this;
}
MyClass & operator<<( double d )
{
// do something with float
return *this;
}
};
int main()
{
MyClass foo;
foo << 42 << 3.14 << 0.1234 << 23;
return 0;
}
It is pretty general, and Goz has already covered some of the points. A few more:
1) A variable argument list gives undefined behavior if you pass anything but POD objects. Overloaded functions can receive any kind of objects.
2) You can have ambiguity if one member of an overload set takes a variable argument list. Then again, you can have ambiguity without that as well. The variable argument list might create ambiguity in a larger number of situations though.
The first point is the really serious one -- for most practical purposes, it renders variable argument lists purely a "legacy" item in C++, not something to even consider using in any new code. The most common alternative is chaining overloaded operators instead (e.g. iostream inserters/extractors versus printf/scanf).