【问题标题】:c++ constructor default parametersc++构造函数默认参数
【发布时间】:2014-07-09 22:36:57
【问题描述】:

如何编写指定默认参数值的构造函数,

#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;
    }
};

然后使用它只传递一些值而不考虑它们的顺序?

例如:这行得通:

char tmp;
foo f( &tmp );

但这不是:

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]

【问题讨论】:

    标签: c++ c++11 parameters constructor default-value


    【解决方案1】:

    简而言之,你不能忽略顺序。

    但是,您可以创建多个构造函数。

    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) {}
    };
    

    编辑:

    顺便说一句,使订单可变/可忽略并不总是一个好主意。这有时会导致难以找到/调试的模棱两可或意外行为。在我的示例中,使用 NULL 参数调用会导致歧义,例如 here

    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_;
    };
    

    作为提示,请改用明确定义的构造函数/函数重载。

    【讨论】:

    • 在他的例子中,使用NULL 的调用者可能会导致问题,所以我不会说没问题。
    • 允许交换顺序也不是一个好主意,因为这会导致正在维护的构造函数的组合爆炸。
    【解决方案2】:

    顺序是必要的,基于顺序和数据类型函数重载正在工作...... 你可以重载函数来实现你所需要的,比如

    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)
        {
        }
    };
    

    【讨论】:

    • 这不能编译 :D 但是,经过一些更改,它可以在 C++11 中工作:foo(char* p): foo(p, 0) {}foo(int q): foo(q, nullptr) {}
    • 感谢马萨指出我的错误...我会编辑我的帖子
    • @Massa,之前版本的代码在 gcc version 4.8.2 中编译得很好,但我仍然按照你的建议进行了更改,因为我认为这是标准的做法。
    【解决方案3】:

    在 C++ 中无法忽略参数顺序。不过,您可以只使用函数重载和委托构造函数:

    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) {}
    };
    

    另外,考虑添加explicit 以避免使用构造函数进行隐式转换。

    【讨论】:

      【解决方案4】:

      有一个命名参数成语。它允许通过指定参数名称以任何顺序传递参数。它还允许将一些参数保留为默认值,并在单个语句中仅设置选定的参数。使用示例:

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

      成语描述和File实现细节可在http://www.parashift.com/c++-faq/named-parameter-idiom.html获得

      【讨论】:

      • 迄今为止最完美、最优雅的解决方案。谢谢。
      猜你喜欢
      • 1970-01-01
      • 2012-02-26
      • 2016-03-01
      • 1970-01-01
      • 2012-06-30
      • 2014-05-15
      • 1970-01-01
      • 2010-09-16
      相关资源
      最近更新 更多