成员变量作为默认参数?

LI.*_*.LE 2 c++ arguments default-arguments

我使用以下代码得到“非静态成员引用必须相对于特定对象”,

class A{
    int data;
    int _default = 0;
public:
    A(int data, int _default) : data(data), _default(_default) {}
    void set(int data = _default){ this->data = data; }
};

int main(){
    A a1(1, 1); a1.set(10); a1.set();
    A a2(2, 2); a2.set(20);
}
Run Code Online (Sandbox Code Playgroud)

我想做的事?

  • 当我们调用时A.set()A::data设置为A::_default
  • 当我们调用时A.set(a)A::data设置为a

son*_*yao 6

非静态数据成员不能用作默认参数,它们应该从调用方上下文提供。

默认参数中不允许使用非静态类成员(即使它们没有被求值),

你可以提供另一个重载。

class A{
    int data;
    int _default = 0;
public:
    A(int data, int _default) : data(data), _default(_default) {}
    void set(int data){ this->data = data; }
    void set(){ set(this->_default); }
};
Run Code Online (Sandbox Code Playgroud)

  • @LI.LE 认为默认参数是二等公民。他们并不像人们想象的那么好。它们在呼叫站点被替换,即您不能默认使用私人成员 (4认同)

Pet*_*ter 5

来自 2017 C++ 标准,第 11.3.6 节,第 9 段

非静态成员不应出现在默认参数中,除非它作为类成员访问表达式 (8.2.5) 的 id 表达式出现,或者除非它用于形成指向成员的指针 (8.3.1)。

所有其他 C++ 标准(之前和之后)都有类似的声明,尽管措辞和章节编号有所不同。上述“除非”两点均不适用于这种情况。

理论上可以(自 C++17 起)使用std::optional(来自 header <optional>)来避免过载,如下所示。

#include <optional>

class A
{
     int data;
     int _default = 0;
   public:
     // other members omitted
   
     void set(std::optional<int> data = std::optional<int>())
     {
         this->data = data.has_value() ? data.value() : _default;
     };
 };
Run Code Online (Sandbox Code Playgroud)

或(如 Jarod42 在评论中所建议的)

     void set(std::optional<int> data = std::nullopt)
     {
         this->data = data.value_or(_default);
     };
Run Code Online (Sandbox Code Playgroud)

我在上面使用“名义上”这个词是因为,就我个人而言,我只会使用两个重载。对于普通人来说(可以说)更容易理解并使用所有 C++ 标准(不仅仅是因为 C++17)

 void set(int data){ this->data = data; }
 void set(){ set(this->_default); }       
Run Code Online (Sandbox Code Playgroud)