Saya memiliki fungsi dengan nama yang sama, tetapi dengan tanda tangan yang berbeda di kelas dasar dan turunan. Ketika saya mencoba menggunakan fungsi kelas dasar di kelas lain yang mewarisi dari turunan, saya menerima pesan kesalahan. Lihat kode berikut:
class A
{
public:
void foo(string s){};
};
class B : public A
{
public:
int foo(int i){};
};
class C : public B
{
public:
void bar()
{
string s;
foo(s);
}
};
Saya menerima kesalahan berikut dari kompiler gcc:
In member function `void C::bar()': no matching function for call to `C::foo(std::string&)' candidates are: int B::foo(int)
Jika saya menghapus int foo(int i){};
dari kelas B
, atau jika saya mengganti namanya foo1
, semuanya berfungsi dengan baik.
Apa masalahnya dengan ini?
Jawaban:
Fungsi di kelas turunan yang tidak menggantikan fungsi di kelas dasar tetapi memiliki nama yang sama akan menyembunyikan fungsi lain dengan nama yang sama di kelas dasar.
Secara umum dianggap praktik yang buruk untuk memiliki fungsi di kelas turunan yang memiliki nama yang sama dengan fungsi di kelas bass yang tidak dimaksudkan untuk menimpa fungsi kelas dasar karena yang Anda lihat biasanya bukan perilaku yang diinginkan. Biasanya lebih baik memberikan nama yang berbeda untuk fungsi yang berbeda.
Jika Anda perlu memanggil fungsi dasar, Anda perlu mencakup panggilan dengan menggunakan
A::foo(s)
. Perhatikan bahwa ini juga akan menonaktifkan mekanisme fungsi virtual apa punA::foo(string)
pada waktu yang sama.sumber
Itu karena pencarian nama berhenti jika menemukan nama di salah satu basis Anda. Itu tidak akan terlihat di pangkalan lain. Fungsi di B membayangi fungsi di A. Anda harus mendeklarasikan kembali fungsi A dalam lingkup B, sehingga kedua fungsi tersebut terlihat dari dalam B dan C:
class A { public: void foo(string s){}; }; class B : public A { public: int foo(int i){}; using A::foo; }; class C : public B { public: void bar() { string s; foo(s); } };
Sunting: Deskripsi sebenarnya yang diberikan Standar adalah (dari 10.2 / 2):
Ini memiliki yang berikut untuk dikatakan di tempat lain (tepat di atasnya):
([...] dimasukkan oleh saya). Perhatikan bahwa meskipun foo Anda di B bersifat pribadi, foo di A tetap tidak akan ditemukan (karena kontrol akses terjadi nanti).
sumber
void A::foo(class basic_string<char,char_traits<char>,allocator<char> >)' in
kelas B 'karena metode lokal ʻint B :: foo (int)' dengan nama yang sama. Mungkin karena saya menggunakan versi lama gcc