I have to write constructor with two default parameters.
func(int arg1 , char* arg2 = "arg2", int arg3 = 1) //example
I am provided the scenario where the constructor is called and a value is given to arg1
and arg2
and arg3
is expected to use a default value. Then another object is instantiated and a value is given to arg1
and arg3
, and default value for arg2
is expected to be used.
Now the problem is, you "can't skip" default parameters is what I'm reading from the text and online. It's saying to order the default paramters from its likliness of being overloaded, but the scenario has one default parameter used while the other isn't. The hints for this question tells me to reorder the parameters/arguments. However, no amount of reordering that I've done seem to be able to resolve this issue.
Also, overloaded constructors can not be used. This has to be done by one constructor.
So how would one do this? I'm stumped and going a bit crazy over this :(
In C++, display () is used to call without passing any arguments. In the above example, it uses both default parameters are c= '*' and n=8. Display ('#') is used to call only one argument.
Default Arguments in C++ A default argument is a value provided in a function declaration that is automatically assigned by the compiler if the calling function doesn't provide a value for the argument. In case any value is passed, the default value is overridden.
No you cannot overload functions on basis of value of the argument being passed, So overloading on the basis of value of default argument is not allowed either. You can only overload functions only on the basis of: Type of arguments. Number of arguments.
Characteristics for defining the default argumentsThe values passed in the default arguments are not constant. These values can be overwritten if the value is passed to the function. If not, the previously declared value retains. During the calling of function, the values are copied from left to right.
Also, overloaded constructors can not be used. This has to be done by one constructor.
The only reason I can think of for this requirement is that the optional arguments have the same type. In that case, you're stuck and you'll want to look into the named constructor and/or named parameter idioms.
Otherwise, just define the extra constructor. This may involve some duplication wrt. the default values.
Foo(int arg1 , char const *arg2 = "arg2", int arg3 = 1)
{
construct(arg1, arg2, arg3);
}
Foo(int arg1, int arg3)
{
construct(arg1, "arg2", arg3);
}
If you're allowed to pass an empty C-string when you've got no value for the second parameter, you could use a helper functor that'll check arg2
and return default value if it's empty. Something like this:
#define DEFAULT_ARG "arg2"
struct helper_class {
char* operator()(char* arg)
{
if (*arg) return arg; else return DEFAULT_ARG;
}
} helper;
class func {
public:
func(int arg1 , char* arg2 = "arg2", int arg3 = 1) {}
};
int main()
{
func f1(42, helper(""), 9001); // default 2nd argument
func f2(42, helper("Its over 9000!"));
}
Not pretty, I know...
Peculiar restriction, that there must be only one constructor. Here's the closest I can think of:
#include <iostream>
// cheap and cheerful Boost.Variant
struct StringOrInt {
char *s;
int i;
bool is_string;
StringOrInt(char *s) : s(s), i(0), is_string(true) {}
StringOrInt(int i) : s(0), i(i), is_string(false) {}
bool isInt() { return !is_string; }
int asInt() { return i; }
char *asString() { return s; }
};
struct Foo {
int m1;
char *m2;
int m3;
Foo(int arg1, StringOrInt arg2 = "arg2", int arg3 = 1) : m1(arg1) {
if (arg2.isInt()) {
arg3 = arg2.asInt();
arg2 = "arg2";
}
m2 = arg2.asString();
m3 = arg3;
}
void print() {
std::cout << m1 << " " << m2 << " " << m3 << "\n";
}
};
int main() {
Foo(1, "HelloWorld").print();
Foo(1, 2).print();
}
Note that with GCC this generates warnings, since the conversion from a string literal to non-const char*
is deprecated and unwise. But it's what you asked for, and fixing it so that the char*
parameters and data member are const char*
is easy enough.
A significant weakness is that this doesn't stop you writing Foo(1,2,3)
. To check that at compile-time I think you need multiple constructors. To check it at runtime, you could make the third parameter into another class, DefaultOrInt
, where Default
is a type used just for this purpose, supporting only one value used as the default value of arg3
. Then if arg2.isInt()
is true, check arg3.isInt()
is false and if not throw logic_error
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With