Ada masalah yang sangat nyata dengan pustaka bersama yang dielakkan oleh idiom pimpl dengan rapi yang tidak dapat dilakukan oleh virtual murni: Anda tidak dapat dengan aman mengubah / menghapus anggota data kelas tanpa memaksa pengguna kelas untuk mengkompilasi ulang kode mereka. Itu mungkin dapat diterima dalam beberapa keadaan, tetapi tidak misalnya untuk perpustakaan sistem.
Untuk menjelaskan masalah secara mendetail, pertimbangkan kode berikut di pustaka / header bersama Anda:
// header
struct A
{
public:
A();
// more public interface, some of which uses the int below
private:
int a;
};
// library
A::A()
: a(0)
{}
Kompilator memancarkan kode di pustaka bersama yang menghitung alamat integer yang akan diinisialisasi menjadi offset tertentu (mungkin nol dalam kasus ini, karena itu satu-satunya anggota) dari penunjuk ke objek A yang diketahuinya this
.
Di sisi pengguna kode, new A
pertama-tama akan mengalokasikan sizeof(A)
byte memori, kemudian menyerahkan pointer ke memori itu ke A::A()
konstruktor sebagaithis
.
Jika dalam revisi perpustakaan Anda nanti Anda memutuskan untuk melepaskan bilangan bulat, membuatnya lebih besar, lebih kecil, atau menambahkan anggota, akan ada ketidakcocokan antara jumlah alokasi kode memori pengguna, dan offset yang diharapkan kode konstruktor. Kemungkinan akibatnya adalah crash, jika Anda beruntung - jika Anda kurang beruntung, perangkat lunak Anda berperilaku aneh.
Dengan pimpl'ing, Anda dapat dengan aman menambah dan menghapus anggota data ke kelas dalam, karena alokasi memori dan panggilan konstruktor terjadi di pustaka bersama:
// header
struct A
{
public:
A();
// more public interface, all of which delegates to the impl
private:
void * impl;
};
// library
A::A()
: impl(new A_impl())
{}
Yang perlu Anda lakukan sekarang adalah menjaga antarmuka publik Anda bebas dari anggota data selain penunjuk ke objek implementasi, dan Anda aman dari kelas kesalahan ini.
Sunting: Saya mungkin harus menambahkan bahwa satu-satunya alasan saya berbicara tentang konstruktor di sini adalah karena saya tidak ingin memberikan lebih banyak kode - argumen yang sama berlaku untuk semua fungsi yang mengakses anggota data.