簡體   English   中英

如何避免通過虛擬繼承調用過多的參數化構造函數?

[英]How to avoid calling a too much parameterized constructor, with virtual inheritance?

我想通過以下明顯的示例執行虛擬繼承:

class A
{
public:
    A(int a) : m_a(a) {}
private:
    int m_a;
};

class B : virtual public A
{
public:
    B(int a, int b) : A(a), m_b(b) {}
private:
    int m_b;
};

class C : virtual public A
{
public:
    C(int a, int c) : A(a), m_c(c) {}
private:
    int m_c;
};

class D : public B, public C
{
public:
    D(int a, int b, int c) : A(a), B(a, b), C(a, c) {}
};

但我不想調用B(a,b)和C(a,c),因為對於虛擬繼承的這種特殊情況,參數B在B和C構造函數中沒有用。

我發現以下文章,其中Jack Reeves提出了一些替代方案來調用默認構造函數。

http://www.drdobbs.com/cpp/multiple-inheritance-considered-useful/184402074?pgno=2

引用:

如果必須先完全初始化A,然后才能構造B和C,則必須對構造函數進行初始化,然后返回到我最初顯示的內容。 另外,也許您可​​以通過以下方式獲得幫助:

class B : public virtual A {  // class C is similar
public:
    B(int x) : A(x) {}
protected:
    B() : A(0) {}
};
class D : public B, public C {
public:
    D(int x) : A(x) {}  // B and C are default constructed
};

報價結束。

因此,我保留了受保護的構造方法的想法,但是我不想使用默認的構造方法。 我已經在A中實現了單個參數構造函數(在實踐中從未調用過),該構造函數使用正向構造函數訪問類內部的“最簡單”有效構造函數(保持B和C在A內部調用的封裝)。 此處,單個參數為該“ Bastard”構造函數賦予唯一簽名。

// new way
namespace VIRTUAL_INHERITANCE {
struct NEVER_CALLED {};
}

class A
{
public:
    A(int a) : m_a(a) {}
protected:
    A(VIRTUAL_INHERITANCE::NEVER_CALLED vinc) : A(0) {}
private:
    int m_a;
};

class B : virtual public A
{
public:
    B(int a, int b) : A(a), m_b(b) {}
protected:
    B(int b) : A(VIRTUAL_INHERITANCE::NEVER_CALLED()), m_b(b) {}
private:
    int m_b;
};

class C : virtual public A
{
public:
    C(int a, int c) : A(a), m_c(c) {}
protected:
    C(int c) : A(VIRTUAL_INHERITANCE::NEVER_CALLED()), m_c(c) {}
private:
    int m_c;
};

class D : public B, public C
{
public:
    D(int a, int b, int c) : A(a), B(b), C(c) {}
};

我的問題是:

  • 如何避免通過虛擬繼承調用過多的參數化構造函數?

  • 是否可以改進“獨特簽名”技術來做其他事情(例如使用枚舉)?

  • 有沒有人有更好的技術來執行相同的事情而不必在A中定義第二個構造函數?

  • 有什么缺點?

我的答案是:

  • 使用默認構造函數,
  • 是的,可以使用enum
  • 否。如果希望編譯器強制您顯式調用 A的構造函數,則必須聲明其他構造函數 但是,如果您不...將默認構造函數與init函數一起使用, 僅使用常規的參數化構造函數,
  • 具有“唯一簽名”構造函數的缺點:
    • A類中A更多代碼,
    • B類中的更多代碼,
    • C類中的更多代碼,
    • 由於采用了虛擬結構,因此代碼更多。
  • 使用“ init”功能的默認c-tor的缺點:
    • 您必須記住要調用init函數參數化的構造函數

樣本(未整理)代碼:

class A
{
public:
    A(int a) : m_a(a) {}
protected:
    A() = default;
    void initA(int a) { m_a = a; } // optional
private:
    int m_a;
};

class B : virtual public A
{
public:
    B(int a, int b) : A(a), m_b(b) {}
protected:
    B(int b) : m_b(b) {}
private:
    int m_b;
};

class C : virtual public A
{
public:
    C(int a, int c) : A(a), m_c(c) {}
protected:
    C(int c) : m_c(c) {}
private:
    int m_c;
};

class D : public B, public C
{
public:
    D(int a, int b, int c) : A(a), B(b), C(c) {}
    // or optionally:
    D(int a, int b, int c) : B(b), C(c) { initA(a); }
};

暫無
暫無

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

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