Najpierw zastanówmy się, dlaczego chcesz mieć klasę bazową. Przychodzi mi do głowy kilka różnych powodów:
- Do obsługi operacji ogólnych lub kolekcji, które będą działać na obiektach dowolnego typu.
- Włączanie różnych procedur, które są wspólne dla wszystkich obiektów (np. Zarządzanie pamięcią).
- Wszystko jest przedmiotem (bez prymitywów!). Niektóre języki (takie jak Objective-C) nie mają tego, co sprawia, że rzeczy są dość chaotyczne.
Są to dwa dobre powody, dla których języki marki Smalltalk, Ruby i Objective-C mają klasy bazowe (technicznie rzecz biorąc, Objective-C tak naprawdę nie ma klasy bazowej, ale pod każdym względem ma).
W przypadku # 1 potrzeba klasy bazowej, która ujednolica wszystkie obiekty w jednym interfejsie, została wyeliminowana przez włączenie szablonów w C ++. Na przykład:
void somethingGeneric(Base);
Derived object;
somethingGeneric(object);
jest niepotrzebne, gdy można zachować integralność typu przez cały czas za pomocą polimorfizmu parametrycznego!
template <class T>
void somethingGeneric(T);
Derived object;
somethingGeneric(object);
W przypadku # 2, podczas gdy w Objective-C procedury zarządzania pamięcią są częścią implementacji klasy i są dziedziczone z klasy bazowej, zarządzanie pamięcią w C ++ jest wykonywane przy użyciu kompozycji, a nie dziedziczenia. Na przykład możesz zdefiniować inteligentne opakowanie wskaźnika, które będzie wykonywać zliczanie referencji na obiektach dowolnego typu:
template <class T>
struct refcounted
{
refcounted(T* object) : _object(object), _count(0) {}
T* operator->() { return _object; }
operator T*() { return _object; }
void retain() { ++_count; }
void release()
{
if (--_count == 0) { delete _object; }
}
private:
T* _object;
int _count;
};
Wtedy zamiast wywoływać metody w samym obiekcie, będziesz wywoływał metody w jego opakowaniu. Pozwala to nie tylko na bardziej ogólne programowanie: pozwala również na oddzielenie problemów (ponieważ w idealnym przypadku obiekt powinien być bardziej zainteresowany tym, co powinien robić, niż tym, jak jego pamięć powinna być zarządzana w różnych sytuacjach).
Wreszcie, w języku, który ma zarówno prymitywy, jak i rzeczywiste obiekty, takie jak C ++, korzyści z posiadania klasy bazowej (spójny interfejs dla każdej wartości) są tracone, ponieważ wtedy masz pewne wartości, które nie mogą być zgodne z tym interfejsem. Aby użyć prymitywów w takiej sytuacji, musisz podnieść je do obiektów (jeśli Twój kompilator nie zrobi tego automatycznie). Stwarza to wiele komplikacji.
A więc krótka odpowiedź na twoje pytanie: C ++ nie ma klasy bazowej, ponieważ mając polimorfizm parametryczny za pośrednictwem szablonów, nie musi.