การเริ่มต้นสมาชิกขณะใช้ตัวสร้างที่ได้รับมอบหมาย


98

ฉันได้เริ่มลองใช้มาตรฐาน C ++ 11 แล้วและฉันพบคำถามนี้ซึ่งอธิบายถึงวิธีการเรียก ctor ของคุณจาก ctor อื่นในคลาสเดียวกันเพื่อหลีกเลี่ยงการมีวิธีการเริ่มต้นหรือสิ่งที่คล้ายกัน ตอนนี้ฉันกำลังลองสิ่งเดียวกันกับรหัสที่มีลักษณะดังนี้:

hpp:

class Tokenizer
{
public:
  Tokenizer();
  Tokenizer(std::stringstream *lines);
  virtual ~Tokenizer() {};
private:
  std::stringstream *lines;
};

cpp:

Tokenizer::Tokenizer()
  : expected('=')
{
}

Tokenizer::Tokenizer(std::stringstream *lines)
  : Tokenizer(),
    lines(lines)
{
}

แต่นี่ทำให้ฉันเกิดข้อผิดพลาด: In constructor ‘config::Tokenizer::Tokenizer(std::stringstream*)’: /path/Tokenizer.cpp:14:20: error: mem-initializer for ‘config::Tokenizer::lines’ follows constructor delegationฉันได้ลองย้ายส่วน Tokenizer () ก่อนและสุดท้ายในรายการ แต่ไม่ได้ช่วย

อะไรคือสาเหตุที่อยู่เบื้องหลังสิ่งนี้และฉันควรแก้ไขอย่างไร ฉันได้ลองขยับlines(lines)ร่างกายด้วยthis->lines = lines;แทนแล้วก็ใช้ได้ดี แต่ฉันอยากจะใช้รายการตัวเริ่มต้นจริงๆ

คำตอบ:


120

เมื่อคุณมอบหมายการเริ่มต้นสมาชิกให้กับตัวสร้างอื่นมีข้อสันนิษฐานว่าตัวสร้างอื่นเริ่มต้นอ็อบเจ็กต์อย่างสมบูรณ์รวมถึงสมาชิกทั้งหมด (เช่นรวมถึงlinesสมาชิกในตัวอย่างของคุณ) คุณจึงไม่สามารถเริ่มต้นสมาชิกใด ๆ ได้อีก

คำพูดที่เกี่ยวข้องจาก Standard คือ (ของฉันเน้น):

(§12.6.2 / 6) mem-initializer-list สามารถมอบหมายให้กับคอนสตรัคเตอร์อื่นของคลาสคอนสตรัคเตอร์โดยใช้คลาสหรือเดสก์ไทป์ใด ๆ ที่แสดงถึงคลาสของคอนสตรัคเตอร์เอง ถ้า mem-initializer-id กำหนดคลาสของคอนสตรัคเตอร์มันจะเป็น mem-initializerเท่านั้น คอนสตรัคเตอร์คือคอนสตรัคเตอร์ที่มอบหมายและคอนสตรัคเตอร์ที่เลือกโดยคอนสตรัคเตอร์เป้าหมาย [... ]

คุณสามารถหลีกเลี่ยงสิ่งนี้ได้โดยการกำหนดเวอร์ชันของตัวสร้างที่รับอาร์กิวเมนต์ก่อน :

Tokenizer::Tokenizer(std::stringstream *lines)
  : lines(lines)
{
}

จากนั้นกำหนดตัวสร้างเริ่มต้นโดยใช้การมอบหมาย:

Tokenizer::Tokenizer()
  : Tokenizer(nullptr)
{
}

ตามกฎทั่วไปคุณควรระบุเวอร์ชันของตัวสร้างที่รับอาร์กิวเมนต์จำนวนมากที่สุดจากนั้นมอบหมายจากเวอร์ชันอื่น ๆ (โดยใช้ค่าดีฟอลต์ที่ต้องการเป็นอาร์กิวเมนต์ในการมอบหมาย)


2
ดูเหมือนว่าจะใช้งานง่ายในตอนแรก แต่ช่วยได้จริง!
Korchkidu
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.