Ostatnio pracowałem nad fragmentem kodu C++ dla projektu pobocznego (cpp-markdown
library, dla ciekawskich), i wpadłem na pytanie o kodowanie, na które chciałbym się wypowiedzieć.Unikanie dynamic_cast/RTTI
cpp-markdown
ma klasę podstawową o nazwie Token
, która ma pewną liczbę podklas. Dwie główne podklasy to Container
(która przechowuje zbiory innych Token
s) i TextHolder
(używane jako klasa podstawowa dla Token
s, które zawierają tekst, oczywiście).
Większość przetwarzania jest obsługiwana za pomocą funkcji wirtualnych, ale niektóre z nich były lepiej obsługiwane w ramach jednej funkcji. W tym celu użyłem dynamic_cast
, aby obniżyć wskaźnik z Token*
do jednej z jego podklas, więc mogłem wywoływać funkcje, które są specyficzne dla podklasy i jej klas potomnych. Nie ma szans, aby rzutowanie zakończyło się niepowodzeniem, ponieważ kod jest w stanie stwierdzić, kiedy takie rzeczy są potrzebne za pośrednictwem funkcji wirtualnych (takich jak isUnmatchedOpenMarker
).
Istnieją dwa inne sposoby Widziałam obsłużyć to:
Tworzenie wszystko funkcji, które chcę zadzwonić jako wirtualne funkcje
Token
i po prostu zostawić je z pustym ciała dla każda podklasa wyjątkiem jednego (ów), które muszą je obsługiwać, albo ...Tworzenie funkcji wirtualnego w
Token
że zwrotu prawidłowo wpisany wskaźnikthis
kiedy to się nazywa w niektórych podtypów i null pointer jeśli został wywołany na cokolwiek innego. Zasadniczo rozszerzenie wirtualnego systemu funkcji, którego już tam używam.
Druga metoda wydaje mi się lepsza niż dotychczasowa i pierwsza. Ale chciałbym poznać innych doświadczonych twórców C++. A może martwię się zbytnio o bzdury. :-)
Uzgodnione, jeśli już sprawdzasz typ za pomocą funkcji wirtualnej, wtedy dynamic_cast jest bezużyteczne. Oba wasze inne rozwiązania to po prostu białe pranie, że wasza hierarchia jest zepsuta. Jeśli chcesz się włamać, użyj przynajmniej szybszego hacka. – BigSandwich
static_cast nie działa, jeśli klasa pochodna używa dziedziczenia wirtualnego do dziedziczenia z tokena. dynamic_cast nie byłby w tym przypadku bezużyteczny. – bk1e