class B {
virtual int foo();
};
class D : public B {
virtual int foo() { cout<<"D\n"; }
};
int B::foo()
{
/* how do i tell if this->foo() is overridden by a subclass, or if it will */
/* simply recurse into B::foo()? */
this->foo();
}
main()
{
D d;
d.B::foo();
}
Odpowiedz
Odpowiedź: nie można.
Zostałabym rozwinięta, gdyby było coś do rozszerzenia.
to też myślałem. – deltamind106
Najbezpieczniejszym sposobem jest nie przesłonięcie foo() w ogóle, ale pozwalają na nadpisanie funkcji OnFoo(), która jest wywoływana z baseclass, jeśli nie możesz ufać swoim programistom. MFC robi to dużo, aby zapewnić pewne domyślne zachowanie (zamiast chronić się przed powtarzaniem).
Następnie, również na poziomie statycznym, wszystko, co implementuje OnFoo(), jest łatwo zauważalne dzięki "Znajdź w plikach".
E.g. (Nie testowane na składni/kompilacji i nie THREADSAFE)
class B
{
public:
B()
{
m_bInFoo=false;
}
int foo()
{
if(!m_bInFoo)
{
m_bInFoo=true;
int nRet = OnFoo();
m_bInFoo=false;
return nRet;
}
return 0;// probably throw exception
}
protected:
// inherited classes override OnFoo(), and never call OnFoo();
virtual int OnFoo(){ return 0 };
private:
bool m_bInFoo;
}
Nienawidzę nawet zapewniając tym .. ale tutaj jest
int B::foo()
{
std::cout << "B" << std::endl;
if (typeid (*this) != typeid(B))
this->foo();
return 0;
}
Edit
Chcę udowodnić, że to działa w MSVC++ 2010.
#include "stdafx.h"
#include <iostream>
class B {
public:
virtual int foo();
};
class D : public B {
public:
virtual int foo() {
std::cout<<"D\n"; return 0;
}
};
int B::foo()
{
std::cout << "B" << std::endl;
/* how do i tell if this->foo() is overridden by a subclass, or if it will */
/* simply recurse into B::foo()? */
if (typeid (*this) != typeid(B))
this->foo();
return 0;
}
int main(int argc, _TCHAR* argv[])
{
D d;
d.B::foo();
B b;
b.foo();
return 0;
}
Ou tput
B
D
B
Dowód, że nie zawsze będzie działać
Zmień D do tego i nie będzie już pracować
class D : public B { };
To nie działa. Nie jest powiedziane, czy foo() jest przesłonięte, i w rzeczywistości, jeśli nie jest to twój kod będzie nieskończenie rekurencyjny przy każdym wywołaniu foo() na obiekcie D; dokładnie to, co OP chce uniknąć. W rzeczywistości nie pomaga ci dowiedzieć się niczego poza tym, czy B, do którego odwołuje się foo(), jest w rzeczywistości bardziej szczegółową wersją czy nie ... to wszystko. Punkty byłyby bardziej znaczące, gdyby ludzie nie tylko rozdawali je przed sprawdzeniem poprawności odpowiedzi. –
@ Noah Roberts Masz rację, jeśli D nie zastąpi B :: foo, to się powtórzy. Można to również rozwiązać za pomocą rozwijania stosu. Utwórz zmienną na stosie, która ustawia flagę w wątku lokalnego magazynu po wprowadzeniu B :: foo(), jeśli B: foo() zostanie ponownie wpisany przez ten sam stos i spróbuje utworzyć inną zmienną, może sprawdzić, czy flaga flaga została ustawiona, a następnie zakończ. Po rozwinięciu stosu zniszczenie zmiennej może zdezaktywować flagę. Moje rozwiązanie rozwiązuje dokładnie problem, który podał, co jest moją winą, ponieważ nie przeczytałem innych scenariuszy, które mogłyby się wydarzyć. –
Jednym ze sposobów jest, aby foo()
czystą funkcję wirtualną w B
, i również go definiują. W ten sposób upewnisz się, że klasy pochodne muszą zdefiniować B
zdefiniować foo()
. Oto B,
class B
{
public:
virtual int foo() = 0; //pure virtual function
};
//pure virtual function also has a default implementation!
int B::foo()
{
std::cout << "B" << std::endl;
this->foo(); //this will call the overridden foo() in the derived class!
return 0;
}
Jeśli klasa pochodzi od B nie realizuje foo(), to nie można nawet utworzyć instancję tej klasy pochodnej!
Zobacz pełny kod pracujący w ideone: http://www.ideone.com/m8O2s
Nawiasem mówiąc, moja osobista opinia byłby taki projekt zajęć jest zły na początek. Co jeśli zadzwonisz pod numer B::foo()
z klasy pochodnej foo()? Rekurencyjny?
To sprawia, że nie może on utworzyć instancji B. Nie wiemy, czy nadal chce tworzyć obiekty typu B. –
tak, oczywiście, zdaję sobie sprawę, że istnieje kilka sposobów inżynierii wokół niego, ale mój Pytanie brzmi, czy istnieje sposób wbudowany do rtti w C++, aby zrobić to, co chcę. – deltamind106
Jak inni podkreślili, nie ma niezawodnego sposobu, aby to zrobić. Zachęcam do przemyślenia swojego projektu ...
cóż, tak, byłoby miło, gdybym mógł przeprojektować niezręczny kod poprzedniego programisty, ale niestety nie ma go teraz na kartach. – deltamind106
- 1. Przechodząc Klasa pochodna sposobu, który musi zastąpić oczekując klasy bazowej
- 2. Czy można programowo wymusić klasa pochodna, aby przekazać się do klasy bazowej jako typ ogólny?
- 3. Klasa pochodna z Generic T
- 4. Określanie typu zwracanej abstrakcyjnej metody z klasy bazowej według PODKLASA
- 5. Wywołanie prywatnej metody bazowej z klasy pochodnej w C#
- 6. Zdefiniowana klasa bez określenia klasy bazowej?
- 7. C#: Konwersja klasy bazowej do dziecka Klasa
- 8. Która klasa pobiera raport getClass() wewnątrz konstruktora klasy bazowej
- 9. Jak wdrożyć biegle interfejs z klasy bazowej w C++
- 10. Określanie, czy metoda zastępuje inną przy użyciu odbicia?
- 11. Czy klasa pochodna może stać się uncopyable przez deklarowanie konstruktora kopiowania/operatora jako prywatną w klasie bazowej?
- 12. Klasa pochodna od podstawy do podstawy
- 13. Jak wywołać metodę klasy bazowej drugiego poziomu, np. Base.base.GetHashCode()
- 14. Czy konstruktory klasy abstrakcyjnej nie są wywoływane niejawnie, gdy tworzona jest klasa pochodna?
- 15. Rozszerzanie delegata z klasy bazowej
- 16. Jak twierdzić, że klasa zareaguje na metodę klasy z RSpec?
- 17. Wywołanie zastąpiona metody z klasy bazowej
- 18. Wywołanie metody klasy bazowej z konstruktora pochodnego
- 19. Czy Groovy dynamicznie dodaje lub zastępuje metodę w POJO?
- 20. Czy klasa java --classpath zastępuje CLASSPATH lub dołącza do niej?
- 21. Dowiedz się, czy klasa Objective-C przesłania metodę:
- 22. Zastanawiając prywatną pole z klasy bazowej
- 23. wykrywanie chronionych konstruktorów (prawdopodobnie abstrakcyjnych) klasy bazowej
- 24. unique_ptr do klasy bazowej
- 25. Python Dziedziczy z jednej klasy, ale zastępuje metodę wywołującą inną klasę?
- 26. Wywołanie klasy bazowej za
- 27. Wywołanie klasy bazowej metoda
- 28. Określanie, czy odwołanie do klasy C#
- 29. Warunkowo dziedziczą z klasy bazowej czysty
- 30. Jak odsłonić ukryte przeciążenie z klasy bazowej?
Prawdopodobnie nie ma niezawodnego sposobu. Dlaczego chcesz? –
Zgadzam się z Oli - wystarczy zadzwonić d.foo() jak normalna osoba. – Puppy
Chcę uzupełnić moją odpowiedź o kilka dodatkowych osobistych punktów widzenia. Staram się nigdy nie pytać, dlaczego ktoś chce coś zrobić. Nie wiem, dlaczego chcą coś zrobić, wiem tylko, że zadali pytanie.Myślę, że jest w porządku, aby spróbować rozwiązać ich problem i zapewnić alternatywę, o której mogą nie myśleć, ale stwierdzenia takie jak "rób to jak normalna osoba" nie są ani konstruktywne, ani pomocne. –