簡體   English   中英

如何使用除初始化列表構造函數以外的其他內容為類成員設置默認值

[英]How do I set a default value for a class member with something other than its initializer list constructor

假設我有這樣的事情:

class A
{
public:
    A(int x, int y)
    {
        std::cout << "Constructed from parameters" << std::endl;
    }

    // Non-copyable, non-movable
    A(A const&) = delete;
    A(A&&) = delete;
    A& operator=(A const&) = delete;
    A& operator=(A&&) = delete;
};
    
class B
{
public:
    B() = default;

private:
    A a{1,2};
};
    
int main()
{
    B b;
    return 0;
}

這工作正常,通過調用A的構造函數用默認值初始化a ,並打印Constructed from parameters


那么,讓我們說我要初始化a不同的,所以我添加了一個構造函數初始化值列表,並更改我的代碼:

class A
{
public:
    A(int x, int y)
    {
        std::cout << "Constructed from parameters" << std::endl;
    }
        
    A(std::initializer_list<int> someList)
    {
        std::cout << "Constructed from an initializer list" << std::endl;
    }

    // Non-copyable, non-movable
    A(A const&) = delete;
    A(A&&) = delete;
    A& operator=(A const&) = delete;
    A& operator=(A&&) = delete;
};
    
class B
{
public:
    B() = default;

private:
    A a{1,2,3};
};
    
int main()
{
    B b;
    return 0;
}

一切仍然如我所願,代碼通過調用A的第二個構造函數用默認值初始化a並打印Constructed from an initializer list


現在,假設我想保持A不變,但返回到通過第一個構造函數設置a的默認值。 如果A是可移動的,我可以使用A a = A(1,2); ,但這里不是這種情況,那么我該怎么做呢? 使用該構造函數設置默認值是否完全不可能?

編輯:我正在尋找適用於 C++14 的解決方案,但如果 C++17 或 C++20 中有更好的解決方案,那也是我想知道的。

如果 A 是可移動的,我可以使用A a = A(1,2); ,但這里不是這樣

好吧,對於 C++17 及更高版本,您可以使用A a = A(1,2); 在這里,只要您將其作為聲明/初始化! 以下工作(在您的第二個代碼片段中):

class B {
public:
    B() = default;
private:
    A a = A( 1, 2 ); // No assignment here - just an initialization.
};

並調用“從參數構造”。 這是因為這里沒有實際的賦值操作,只是一個初始化 但是,由於您所述的原因,以下操作將失敗:

class B {
public:
    B() { a = A( 1, 2 ); } // error C2280: 'A &A::operator =(A &&)': attempting to reference a deleted function
private:
    A a{ 1,2,3 };
};

編輯:Pre-C++17,以下是一種解決方法,在B的默認構造函數中的初始值設定項列表中使用“老式”圓括號而不是花括號(在 clang- 中使用 C++14 測試) cl 和 MSVC):

class B {
public:
    B() : a(1,2) {} // Using a{1,2} calls the "initializer list" constructor, however!
private:
    A a;
};

我認為如果沒有某種“黑客”,這在 C++14 中是不可能的。 一種這樣的技巧是使用額外的消歧參數。 例如:

class From_params {};

class A {
public:
    A(int, int, From_params = {})      // (1)
    {}
    
    A(std::initializer_list<int>)      // (2)
    {}

    ...
};

class B {
public:
    B() = default;

private:
    A a{1, 2, From_params{}};  // calls (1)
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM