Saya memiliki kelas dasar dengan fungsi virtual dan saya ingin mengganti fungsi itu di kelas turunan. Adakah cara untuk membuat compiler memeriksa apakah fungsi yang saya deklarasikan di kelas turunan benar-benar menggantikan fungsi di kelas dasar? Saya ingin menambahkan beberapa makro atau sesuatu yang memastikan bahwa saya tidak secara tidak sengaja mendeklarasikan fungsi baru, alih-alih menimpa yang lama.
Ambil contoh ini:
class parent {
public:
virtual void handle_event(int something) const {
// boring default code
}
};
class child : public parent {
public:
virtual void handle_event(int something) {
// new exciting code
}
};
int main() {
parent *p = new child();
p->handle_event(1);
}
Di sini parent::handle_event()
dipanggil alih-alih child::handle_event()
, karena metode anak melewatkan const
deklarasi dan karenanya mendeklarasikan metode baru. Ini juga bisa menjadi kesalahan ketik pada nama fungsi atau beberapa perbedaan kecil dalam tipe parameter. Ini juga dapat dengan mudah terjadi jika antarmuka kelas dasar berubah dan di suatu tempat beberapa kelas turunan tidak diperbarui untuk mencerminkan perubahan tersebut.
Adakah cara untuk menghindari masalah ini, dapatkah saya memberi tahu kompiler atau alat lain untuk memeriksanya untuk saya? Adakah tanda compiler yang berguna (sebaiknya untuk g ++)? Bagaimana Anda menghindari masalah ini?
Jawaban:
Sejak g ++ 4.7, ia memahami
override
kata kunci C ++ 11 yang baru :sumber
override
harus digunakan dalam definisi. Implementasi inline adalah definisi dan implementasi, jadi tidak apa-apa.Sesuatu seperti
override
kata kunci C # bukan bagian dari C ++.Di gcc,
-Woverloaded-virtual
peringatkan agar tidak menyembunyikan fungsi virtual kelas dasar dengan fungsi dengan nama yang sama tetapi tanda tangan yang cukup berbeda sehingga tidak menimpanya. Namun, ini tidak akan melindungi Anda dari kegagalan mengganti fungsi karena salah mengeja nama fungsi itu sendiri.sumber
override
kata kunci di C ++; ini mungkin berarti Anda menggunakan sesuatu yang dapat mengkompilasi beberapa kode sumber C ++ yang tidak valid. ;)override
fungsionalitas gaya C # ; Saya jarang mengalami masalah dengan penggantian yang gagal dan relatif mudah untuk didiagnosis dan diperbaiki. Satu hal yang tidak saya setujui adalah bahwa pengguna VC ++ harus menggunakannya. Saya lebih suka C ++ terlihat seperti C ++ di semua platform bahkan jika satu proyek tertentu tidak perlu portabel. Perlu dicatat bahwa C ++ 0x akan memiliki[[base_check]]
,[[override]]
dan[[hiding]]
atribut sehingga Anda dapat memilih untuk mengganti pemeriksaan jika diinginkan.override
kata kunci yang tampaknya itu tidak . Nah, bukan kata kunci yang tepat tetapi pengenal khusus di C ++ 11. Microsoft mendorong cukup keras untuk membuat kasus khusus ini dan mengikuti format umum untuk atribut danoverride
membuatnya menjadi standar :)Sejauh yang saya tahu, tidak bisakah Anda membuatnya abstrak?
Saya pikir saya membaca di www.parashift.com bahwa Anda benar-benar dapat menerapkan metode abstrak. Yang masuk akal bagi saya secara pribadi, satu-satunya hal yang dilakukannya adalah memaksa subclass untuk mengimplementasikannya, tidak ada yang mengatakan apa-apa tentang itu tidak diizinkan untuk memiliki implementasi itu sendiri.
sumber
BaseClass::method()
) dipanggil dalam implementasi turunan (katakanlahDerivedClass::method()
), misalnya untuk nilai default.Di MSVC, Anda dapat menggunakan
override
kata kunci CLR meskipun Anda tidak sedang mengkompilasi untuk CLR.Di g ++, tidak ada cara langsung untuk menerapkannya di semua kasus; orang lain telah memberikan jawaban yang baik tentang cara menangkap perbedaan tanda tangan menggunakan
-Woverloaded-virtual
. Di versi mendatang, seseorang mungkin menambahkan sintaks seperti__attribute__ ((override))
atau yang setara menggunakan sintaks C ++ 0x.sumber
Di MSVC ++ Anda dapat menggunakan kata kunci
override
override
berfungsi baik untuk kode asli dan CLR di MSVC ++.sumber
Buat fungsi menjadi abstrak, sehingga kelas turunan tidak memiliki pilihan lain selain menimpanya.
@Ray Kode Anda tidak valid.
Fungsi abstrak tidak boleh memiliki badan yang ditentukan sebaris. Ini harus dimodifikasi untuk menjadi
sumber
Saya akan menyarankan sedikit perubahan dalam logika Anda. Ini mungkin berhasil atau tidak, tergantung pada apa yang perlu Anda capai.
handle_event () masih dapat melakukan "kode default yang membosankan" tetapi alih-alih menjadi virtual, pada titik di mana Anda ingin melakukan "kode baru yang menarik" buatlah kelas dasar memanggil metode abstrak (yaitu harus-ditimpa) metode yang akan diberikan oleh kelas turunan Anda.
EDIT: Dan jika Anda kemudian memutuskan bahwa beberapa kelas turunan Anda tidak perlu memberikan "kode baru yang menarik" maka Anda dapat mengubah abstrak menjadi virtual dan menyediakan implementasi kelas dasar kosong dari fungsionalitas "yang disisipkan".
sumber
Kompilator Anda mungkin memiliki peringatan yang dapat dihasilkan jika fungsi kelas dasar disembunyikan. Jika ya, aktifkan. Itu akan menangkap bentrokan const dan perbedaan dalam daftar parameter. Sayangnya ini tidak akan mengungkap kesalahan ejaan.
Misalnya, ini adalah peringatan C4263 di Microsoft Visual C ++.
sumber
override
Kata kunci C ++ 11 ketika digunakan dengan deklarasi fungsi di dalam kelas turunan, itu memaksa kompilator untuk memeriksa bahwa fungsi yang dideklarasikan sebenarnya menimpa beberapa fungsi kelas dasar. Jika tidak, kompilator akan menampilkan kesalahan.Oleh karena itu, Anda dapat menggunakan
override
penentu untuk memastikan polimorfisme dinamis (penggantian fungsi).sumber