2009-02-25 14 views
30

Jeśli mam kod jak poniżej:C++ funkcja członek wirtualnym override i przeciążenie jednocześnie

struct A { 
    virtual void f(int) {} 
    virtual void f(void*) {} 
}; 

struct B : public A { 
    void f(int) {} 
}; 

struct C : public B { 
    void f(void*) {} 
}; 


int main() { 
    C c; 
    c.f(1); 

    return 0; 
} 

pojawia się błąd, który mówi, że próbuję zrobić nieprawidłowy konwersji z int do void *. Dlaczego kompilator nie może stwierdzić, że musi wywołać B :: f, ponieważ obie funkcje są zadeklarowane jako wirtualne?


Po przeczytaniu odpowiedzi Jalfa poszedłem i zmniejszyłem ją jeszcze bardziej. Ten nie działa tak dobrze. Niezbyt intuicyjny.

struct A { 
    virtual void f(int) {} 
}; 

struct B : public A { 
    void f(void*) {} 
}; 


int main() { 
    B b; 
    b.f(1); 

    return 0; 
} 

Odpowiedz

44

Krótka odpowiedź brzmi "ponieważ tak działa przeciążenie w C++".

Kompilator szuka funkcji F w klasie C, a jeśli znajdzie, zatrzyma wyszukiwanie i spróbuje wybrać kandydata spośród nich. Przegląda tylko klasy bazowe, jeśli nie znaleziono pasujących funkcji w klasie pochodnej.

Można jednak wyraźnie przedstawić funkcje klasy bazowej do nazw pochodzących klasy:

struct C : public B { 
    void f(void*) {} 
    using B::f; // Add B's f function to C's namespace, allowing it to participate in overload resolution 
}; 
+3

chcieć dodać link do C++ FAQ na funkcji ukrycia: http://www.parashift.com/c++-faq-lite/strange- inheritance.html # faq-23.9 – greyfade

+0

@jalf: Jaki jest powód takiego zachowania kompilatora? Dlaczego nie szukać klas podstawowych dla funkcji dopasowanych do połączenia? – Andrew

+0

Jaki byłby powód * tego *? Kompilator musi wybrać pewne zachowanie, co w niektórych przypadkach ma sens i wydaje się absurdalne w innych przypadkach. Zaletą tego schematu jest możliwość włączenia zachowania "kontynuuj wyszukiwanie". Ale gdyby tak było, nie byłoby sposobu, aby z niego zrezygnować i uzyskać * to * zachowanie. Pod koniec dnia projektanci języka musieli podjąć decyzję i wybrali to zachowanie. :) – jalf

-6

Dobrze myślę przede wszystkim, że nie rozumiem, co wirtualne mechanizm lub polymorhism. Gdy polimorfizm jest osiągany tylko za pomocą wskaźników obiektów. Myślę, że jesteś nowy w C++. Bez użycia wskaźników obiektu nie ma znaczenia polimorfizm lub użycie wirtualnego słowa kluczowego wskaźnika klasy bazowej i przypisanie do niego pożądanych obiektów klasy pochodnej. Następnie zadzwoń i spróbuj.

-1

Albo można to zrobić:

void main() 
{ 
    A *a = new C(); 
    a->f(1); //This will call f(int) from B(Polymorphism) 
} 
Powiązane problemy