szablony do zrozumienia, że to ogromne korzyści, aby uzyskać terminologii prosto ponieważ sposób mówić o t hem określa sposób myślenia o nich.
W szczególności Area
nie jest klasą szablonu, ale szablonem klasy. Oznacza to, że jest to szablon, z którego można generować klasy. Area<int>
jest taką klasą (to jest obiekt , a nie, ale oczywiście można utworzyć obiekt z tej klasy w ten sam sposób, w jaki można tworzyć obiekty z dowolnej innej klasy). Kolejną taką klasą byłby Area<char>
. Zauważ, że są to całkowicie różne klasy, które nie mają ze sobą nic wspólnego poza faktem, że zostały wygenerowane z tego samego szablonu klasy.
Ponieważnie jest klasą, nie można wyprowadzić z niego klasy Rectangle
. Możesz wyprowadzić klasę tylko z innej klasy (lub kilku z nich).Od Area<int>
jest klasa, można, na przykład, czerpią Rectangle
od niego:
class Rectangle:
public Area<int>
{
// ...
};
ponieważ Area<int>
i Area<char>
są różne klasy, można nawet czerpać z obu jednocześnie (jednak przy dostępie członków nich, będziesz mieć do czynienia z dwuznaczności):
class Rectangle:
public Area<int>,
public Area<char>
{
// ...
};
jednak trzeba określić, które klasyfikowane w celu uzyskania od kiedy można zdefiniować Rectangle
. Jest to prawdą niezależnie od tego, czy te klasy są generowane z szablonu, czy nie. Dwa obiekty tej samej klasy po prostu nie mogą mieć różnych hierarchii dziedziczenia.
Co można zrobić, aby szablon był również szablonem Rectangle
. Jeśli piszesz
template<typename T> class Rectangle:
public Area<T>
{
// ...
};
Masz szablon Rectangle
, z którego można uzyskać klasę Rectangle<int>
wynikającemu z Area<int>
i inną klasę Rectangle<char>
wynikającemu z Area<char>
.
Możliwe, że chcesz mieć pojedynczy typ Rectangle
, dzięki czemu możesz przekazać wszystkie rodzaje Rectangle
do tej samej funkcji (która sama nie musi znać typu obszaru). Ponieważ klasy Rectangle<T>
wygenerowane przez utworzenie szablonu Rectangle
są formalnie niezależne od siebie, nie działa w ten sposób. Można jednak skorzystać z wielokrotne dziedziczenie tutaj:
class Rectangle // not inheriting from any Area type
{
// Area independent interface
};
template<typename T> class SpecificRectangle:
public Rectangle,
public Area<T>
{
// Area dependent stuff
};
void foo(Rectangle&); // A function which works with generic rectangles
int main()
{
SpecificRectangle<int> intrect;
foo(intrect);
SpecificRectangle<char> charrect;
foo(charrect);
}
Jeśli ważne jest, że generyczny Rectangle
jest pochodną ogólnej Area
można zrobić tę samą sztuczkę z Area
też:
class Area
{
// generic Area interface
};
class Rectangle:
public virtual Area // virtual because of "diamond inheritance"
{
// generic rectangle interface
};
template<typename T> class SpecificArea:
public virtual Area
{
// specific implementation of Area for type T
};
template<typename T> class SpecificRectangle:
public Rectangle, // maybe this should be virtual as well, in case the hierarchy is extended later
public SpecificArea<T> // no virtual inheritance needed here
{
// specific implementation of Rectangle for type T
};
Jest to szablon klasy _, ponieważ jest to szablon, z którego generowane są klasy. – sbi