Pertanyaan Referensi ke konstruktor iniside objek tak diinisialisasi


Adalah mungkin untuk melewatkan objek yang tidak diinisialisasi ke kelas induk seperti pada contoh berikut

class C
{
    public:
        C(int i): 
            m_i(i)
        {};

        int m_i;
}

class T
{
    public:
        T(C & c):
            m_c(c)
        {
        };

        C & m_c;
};


class ST : public T
{
    public:
        ST():
            T(m_ci),
            m_ci(999)
        {
        };

        C m_ci;
};

Di class T konstruktor, c adalah referensi ke objek yang tidak diinisialisasi. Jika class T sedang menggunakan c objek selama konstruksi, ini mungkin akan menyebabkan kesalahan. Tapi karena tidak, ini mengkompilasi dan berfungsi dengan baik. Pertanyaan saya adalah - apakah itu rem semacam paradigma atau arahan desain yang baik? Jika demikian, apa alternatifnya, karena saya merasa berguna untuk mengalokasikan objek yang diperlukan oleh orang tua dalam subclass.

Di samping catatan, saya bertanya-tanya mengapa tidak mungkin untuk mengubah urutan inisialisasi, sehingga konstruktor kelas dasar akan dipanggil setelah inisialisasi beberapa anggota.


5
2017-10-22 12:42


asal


Jawaban:


Kamu bisa, tetapi Anda mendapatkan perilaku tidak terdefinisi.

Dalam utilitas Boost, Anda akan menemukan idiom dasar-dari-anggota dibuat oleh R. Samuel Klatchko. Pada dasarnya, Anda membuat basis pribadi di tempat anggota pribadi. Basis ini diinisialisasi terlebih dahulu, dan Anda dapat menggunakannya untuk basis lain:

// ...

class C_base
{
public:
    C_base(int i) :
    m_ci(i)
    {}

    C m_ci;
};


class ST :
    private C_base
    public T
{
    public:
        ST() :
            C_base(999),
            T(m_ci),
        {
        };
};

Utilitas Boost menghilangkan kode berulang.


1
2017-10-22 12:54



Melewati referensi atau penunjuk ke sesuatu yang tidak diinisialisasi secara teknis sangat baik.

Tetapi alasan yang Anda tanyakan mungkin adalah Anda berpikir bahwa sesuatu dengan mudah bisa salah, bahwa melalui beberapa rantai panggilan seseorang mungkin secara tidak sengaja mengakses objek sebelum diinisialisasi. Dan saya pikir itu perhatian yang valid. Dan ada hal lain yang bisa salah, yaitu kode itu di kelas dasar T sekarang dapat membatalkan invariant class dari ST dengan langsung mengubah anggota data ST contoh...

Jadi, saya pikir itu agak berisiko.

Mengenai urutan inisialisasi, C ++ didasarkan pada gagasan membangun dari bagian atas, dalam hirarki. Jika sebuah konstruktor dilemparkan, maka hal-hal yang benar-benar terkonstruksi dihancurkan, secara otomatis. Ini akan lebih sulit atau kurang efisien dengan urutan konstruksi yang lebih sewenang-wenang.

Cheers & Hth.,


3
2017-10-22 12:59



Saya telah melihat ini banyak, dan banyak kompiler akan memperingatkan. Tidak apa jika itu T konstruktor tidak pernah dereferences c referensi.

Jika Anda tidak menginginkan peringatan, Anda perlu melakukan dua tahap konstruksi. Buat yang terlindungi Init(C&) metode dalam T, dan kemudian memanggilnya di ST tubuh konstruktor - sayangnya m_c perlu menjadi penunjuk untuk melakukan itu (karena referensi tidak dapat dipindahkan ke objek lain)


2
2017-10-22 12:54