0

I'm really confused because I can't describe my question well, but I'm sure that many of you will understand me.

#include <iostream>

using namespace std;

void display(int n = 1, char c = '*');

int main()
{
    display();
    display(5);
    display('$');
    return 0;
}

void display(int n, char c)
{
    for (int i = 1; i <= n; i++)
        cout << c;
    cout << endl;
}

At display('$'), I want to pass this char to its parameter c and use n with its default value, which is 1. Can anyone tell me how to do this properly?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
MiDo
  • 67
  • 1
  • 6

3 Answers3

4

You can't as is. When you call a function the parameters get matched from left to right in order. That means display('$'); will give '$' to n instead of c.

What you can do though, at least in this case, is overload the function to do what you want. With

void display(int n, char c);
void display(int n);
void display(char c);
void display();

You can have the void, int and char overload call the main function and hide the fact that your filling in the "blanks". That looks like

void display(int n)
{
    display(n, '*');
}

void display(char c)
{
    display(1, c);
}

void display()
{
    display(1, '*');
}

The down side here is your repeating the default values. That makes this brittle as a change of the default values requires you to change it in multiple places.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • 1
    I would implement `display()` as calling `display(1)` instead, so the default `'*'` char is specified in only one place. Or as calling `display('*')` so the default `1` is specified in only one place. If you want both defaults specified in one place, use global definitions: `const int def_n = 1; const char def_c = '*'; void display(int n) { display(n, def_c); } void display(char c) { display(def_n, c); } void display() { display(def_n, def_c); }` – Remy Lebeau Jul 27 '17 at 20:41
2

Default parameters can only be left out starting from the right. Thus your function

void display(int n = 1, char c = '*');

can only be called as

display();        // same as   display(1,'*');
display(5);       // same as   display(5,'*');
display(5,'a');

There are several ways to deal with this. The easiest in this case (as pointed out in a comment by tadman) would be to provide an overload that simply calls the original function

void display(char c) { display(1,c); }    

You just have to take care that each overload has a different signature, eg you cannot have

void display(char c = '*') { display(1,c); }    

because then a call display() would be ambiguous. If there are more parameters it can make sense to declare a struct

struct Params {
    int n;
    char c;
    Params() : n(1),c('*') {}
};

This scales better with more parameters, because defaults can be used or not in any order:

Params p;
p.c = 'a';
display(p);
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
0

I also found an another way, which is function redefinition.

Instead of

void display(int n = 1, char c = '*') {}

I could replace it with

void display(char c = '*', int n = 1) {}

But function overloading is better, because it will work on all conditions.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
MiDo
  • 67
  • 1
  • 6