简体   繁体   中英

c++ constructor default parameters

How can I write a constructor specifying default parameters values,

#include <iostream>

using namespace std;

struct foo
{
    char *_p;
    int   _q;

    foo( char *p = nullptr, int q = 0 ): _p(p), _q(q)
    {
        cout << "_q: " << _q << endl;
    }
};

and then use it passing only some values without taking into account their order ?

Eg: this works:

char tmp;
foo f( &tmp );

but this doesn't:

foo f( 1 );

$ g++ -O0 -g -Wall -std=c++0x -o test test.cpp
test.cpp: In function ‘int main(int, char**)’:
test.cpp:18:11: error: invalid conversion from ‘int’ to ‘char*’ [-fpermissive]
test.cpp:10:2: error:   initializing argument 1 of ‘foo::foo(char*, int)’ [-fpermissive]

shortly, you can't ignore the order.

but you can create more than one constructor.

struct foo
{
    char *_p;
    int   _q;

    foo( char *p, int q): _p(p), _q(q) {}
    foo( char *p): _p(p), _q(0) {}
    foo( int q): _p(nullptr), _q(q) {}
};

edit:

by the way, it isn't alway's a good idea to make the order variadic/ignorable. this can sometimes lead to ambiguity or unexpected behavior which is hard to find/debug. in my example calling with NULL parameter leads to ambiguity or in something like this :

class foo {
public:
    foo(int x, unsigned char y=0) : x_(x), y_(y) {}
    foo(unsigned char x, int y=0) : x_(y), y_(x) {}

    int  x_;
    char y_;
};

just as a hint, use clearly defined constuctors/ function overloads instead.

There is a Named Parameter Idiom. It allows to pass parameters in any order by specifying their names. It also allows to leave some parameters with default values and set only chosen ones in a single statement. Usage example:

File f = OpenFile("foo.txt")
       .readonly()
       .createIfNotExist()
       .appendWhenWriting()
       .blockSize(1024)
       .unbuffered()
       .exclusiveAccess();

Idiom description and File implementation details are available at http://www.parashift.com/c++-faq/named-parameter-idiom.html

There's no way in C++ to ignore he parameter order. Still, you can just use function overloading and delegating constructors:

struct foo {
    char *_p;
    int   _q;
    // this is the default constructor and can also be used for conversion
    foo( char *p = nullptr, int q = 0 ): _p(p), _q(q)
    {
        cout << "_q: " << _q << endl;
    }
    // this constructor canbe used for conversion.
    foo( int q, char *p = nullptr): foo(p, q) {}
};

Also, consider adding explicit to avoid use of the constructors for implicit conversion.

Order is necessary, based on the order and data type function overloading is working... you can overload the function to achieve you need, like

struct foo
{
    char *_p;
    int   _q;

    foo( char *p, int q): _p(p), _q(q) {}
    foo( int q, char *p): _p(p), _q(q) {}
    foo( char *p):foo(p,0)
    {  
    }
    foo( int q):foo(q,nullptr)
    {
    }
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM