Pertanyaan Mengapa constructor copy implisit memanggil konstruktor copy kelas dasar dan konstruk copy yang ditentukan tidak?


Pertimbangkan hirarki kelas di mana A adalah kelas dasar dan B berasal dari A.

Jika konstruktor salin tidak didefinisikan dalam B, kompilator akan mensintesisnya. Ketika dipanggil, konstruktor salin ini akan memanggil konstruktor copy kelas dasar (bahkan yang disintesis, jika tidak ada yang disediakan oleh pengguna).

#include <iostream>

class A {
    int a;
public:
    A() {
        std::cout << "A::Default constructor" << std::endl;
    }

    A(const A& rhs) {
        std::cout << "A::Copy constructor" << std::endl;
    }
};

class B : public A {
    int b;
public:
    B() {
        std::cout << "B::Default constructor" << std::endl;
    }
};

int main(int argc, const char *argv[])
{
    std::cout << "Creating B" << std::endl;
    B b1;
    std::cout << "Creating B by copy" << std::endl;
    B b2(b1);
    return 0;
}

Keluaran:

Creating B
A::Default constructor
B::Default constructor
Creating B by copy
A::Copy constructor

Jika pengguna mendefinisikan konstruktor salinnya sendiri di B, ketika dipanggil, copy constructor ini akan memanggil konstruktor default kelas dasar, kecuali panggilan ke konstruktor salin kelas dasar secara eksplisit ada (mis. dalam daftar inisialisasi).

#include <iostream>

class A {
    int a;
public:
    A() {
        std::cout << "A::Default constructor" << std::endl;
    }

    A(const A& rhs) {
        std::cout << "A::Copy constructor" << std::endl;
    }
};

class B : public A {
    int b;
public:
    B() {
        std::cout << "B::Default constructor" << std::endl;
    }
    B(const B& rhs) {
        std::cout << "B::Copy constructor" << std::endl;
    }
};

int main(int argc, const char *argv[])
{
    std::cout << "Creating B" << std::endl;
    B b1;
    std::cout << "Creating B by copy" << std::endl;
    B b2(b1);
    return 0;
}

Keluaran:

Creating B
A::Default constructor
B::Default constructor
Creating B by copy
A::Default constructor
B::Copy constructor

Pertanyaan saya adalah, mengapa pengguna tidak mendefinisikan konstruktor menyalin panggilan konstruktor menyalin kelas dasar sebagai perilaku default?


32
2018-02-07 14:42


asal


Jawaban:


Itu hanya cara konstruktor menyalin implisit didefinisikan (tidak masuk akal memanggil default). Segera setelah Anda mendefinisikan konstruktor apa pun (salin atau lainnya), perilaku otomatis normalnya adalah memanggil konstruktor induk default, jadi akan tidak konsisten untuk mengubah itu untuk satu konstruktor spesifik yang ditentukan pengguna.


7
2018-02-07 14:49



Semua konstruktor anak dasar memanggil konstruktor default induk. Ini adalah bagaimana standar didefinisikan. Seperti yang Anda tunjukkan jika Anda ingin kelas dasar B untuk memanggil copy constructor A Anda harus secara eksplisit memintanya

#include <iostream>

class A {
int a;
public:
A() {
    std::cout << "A::Default constructor" << std::endl;
}

A(const A& rhs) {
    std::cout << "A::Copy constructor" << std::endl;
}
};

class B : public A {
int b;
public:
B() {
    std::cout << "B::Default constructor" << std::endl;
}
B(const B& rhs):A(rhs) {
    std::cout << "B::Copy constructor" << std::endl;
}
};

int main(int argc, const char *argv[])
{
std::cout << "Creating B" << std::endl;
B b1;
std::cout << "Creating B by copy" << std::endl;
B b2(b1);
return 0;
}

Hal ini karena compiler tidak dapat mengetahui setiap konstruktor yang berbeda yang mana konstuktor dari induknya harus dipanggil dan karenanya kita memiliki konstruktor default Untuk semua yang lain Anda harus secara eksplisit menyatakannya.


8
2018-02-07 14:54



Jawaban sederhana (mungkin basi) adalah karena Anda tidak memberitahukannya. Karena Anda menulis konstruktor salin turunan, Anda sepenuhnya mengontrol bagaimana ia berperilaku. Kegagalan untuk menentukan panggilan ke basis dan compiler menghasilkan kode untuk menginisialisasi kelas dasar dengan memanggil konstruktor default kelas dasar.


1
2018-02-07 14:50