[英]Why is this attempting to call the default constructor?
在我的原始項目中,我有一個類,該類的構造函數應該在構造類成員之前調用初始化函數。 但是,編譯器給我一個錯誤,提示缺少類成員的默認構造函數。
class One
{
public:
One(int i) {};
};
class Two
{
One one;
public:
Two() {one(0)};
};
int main(void)
{
Two two;
}
編譯器給我這個:
Problem.cpp: In constructor ‘Two::Two()’:
Problem.cpp:12:15: error: no matching function for call to ‘One::One()’
Two() {one(0)};
^
Problem.cpp:4:9: note: candidate: ‘One::One(int)’
One(int i) {};
^~~
Problem.cpp:4:9: note: candidate expects 1 argument, 0 provided
Problem.cpp:1:7: note: candidate: ‘constexpr One::One(const One&)’
class One
^~~
Problem.cpp:1:7: note: candidate expects 1 argument, 0 provided
Problem.cpp:1:7: note: candidate: ‘constexpr One::One(One&&)’
Problem.cpp:1:7: note: candidate expects 1 argument, 0 provided
Problem.cpp:12:21: error: no match for call to ‘(One) (int)’
Two() {one(0)};
為什么此代碼嘗試為Two構造函數中的One調用默認構造函數,以及如何產生預期的行為(構造函數中其他初始化代碼之后的構造成員)?
如何產生預期的行為(在構造函數中其他初始化代碼之后的構造成員)?
這是不可能的。 在C ++中,必須在輸入構造函數的主體之前構造所有對象的基類和非靜態成員變量。
在您的代碼中,您編寫了Two
構造函數的開頭{
,而之前沒有為該成員變量提供任何構造函數參數,因此該成員變量是默認構造的。
如果你有一些邏輯來制定出初始化one
,那么我會建議把該進的功能:
int f() { /* logic here */ return 0; }
// ...
Two(): one( f() ) {}
當然,您也可以向One
添加默認構造函數,以及以后分配給它的方法。
之所以調用默認構造函數,是因為您不調用將int
作為參數的構造函數。 您必須在初始化列表中執行以下操作:
class Two
{
One one;
public:
Two() : one(0) {}
};
您還需要正確聲明變量:
Two two;
不
Two two();
通過添加一個init函數並使用逗號運算符,您可以擺脫這種情況:
class Two
{
One one;
void init()
{
// Initialize things here
}
public:
Two() : one((init(), 0)) {}
};
首先,調用init()
,然后將0
傳遞給One
構造函數。
你需要這個:
class One
{
public:
One(int i) {};
};
class Two
{
One one;
public:
Two() : one(0) {};
};
int main(void)
{
Two two();
}
之所以調用One
的默認構造函數,是因為需要在Two::Two
構造函數的第一行代碼之前構造Two::one
,否則還沒有真正構造Two
。 通過將One
構造函數調用放置在初始化程序列表中,可以確保One
在運行任何未初始化的Two
代碼之前獲取它需要構造的參數。
該錯誤是因為在進入Two()
構造函數的主體之前,必須完全構造Two
的所有成員,但是您沒有在Two()
構造函數的成員初始化列表中顯式構造one
成員,因此編譯器將嘗試默認構造您的one
成員,由於One
類沒有默認構造函數而失敗。
要執行您的要求,您需要:
使One
可以默認構造,並在需要時給它一種分配新值的方法:
class One { private: int value; public: One(int i = 0) : value(i) {} One& operator=(int rhs) { value = rhs; return *this; } }; class Two { private: One one; // <-- default constructed! public: Two() { // initialization as needed... one = 0; // <-- reassignment afterwards } };
將one
成員更改為一個One*
指針,然后您可以隨時構造它,例如:
class One { private: int value; public: One(int i = 0) : value(i) {} One(const One &src) : value(src.value) {} }; class Two { private: One *one; public: Two() : one(NULL) { // initialization as needed... one = new One(0); } // don't forget about the "Rule of 3"... Two(const Two &src) : one(NULL) { // initialization as needed... one = new One(*(src.one)); } ~Two() { delete one; } Two& operator=(const Two &rhs) { if (&rhs != this) { Two temp(rhs); std::swap(one, temp.one); } return *this; } };
或者,如果您使用的是C ++ 11或更高版本:
#include <memory> class Two { private: std::unique_ptr<One> one; public: Two() { // initialization as needed... one.reset(new One(0)); // or: in C++14 and later: // one = std::make_unique<One>(0); } // don't forget about the "Rule of 3"... Two(const Two &src) { // initialization as needed... one.reset(new One(*(src.one))); // or: in C++14 and later: // one = std::make_unique<One>(*(src.one)); } Two& operator=(const Two &rhs) { if (&rhs != this) { Two temp(rhs); std::swap(one, temp.one); } return *this; } // and the "Rule of 5"... Two(Two &&src) { // initialization as needed... one = std::move(src.one); } Two& operator=(Two &&rhs) { one = std::move(rhs.one); return *this; } };
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.