Untuk memahami template, sangat bermanfaat untuk meluruskan terminologinya karena cara Anda membicarakannya menentukan cara memikirkannya.
Secara khusus, Area
ini bukan kelas template, tapi template kelas. Artinya, ini adalah template tempat kelas dapat dibuat. Area<int>
adalah kelas seperti itu (ini bukan objek, tetapi tentu saja Anda dapat membuat objek dari kelas itu dengan cara yang sama seperti Anda membuat objek dari kelas lain). Kelas lain seperti itu Area<char>
. Perhatikan bahwa itu adalah kelas yang sama sekali berbeda, yang tidak memiliki kesamaan apa pun kecuali fakta bahwa mereka dihasilkan dari template kelas yang sama.
Karena Area
bukan kelas, Anda tidak dapat memperoleh kelas Rectangle
darinya. Anda hanya dapat memperoleh satu kelas dari kelas lain (atau beberapa di antaranya). Karena Area<int>
merupakan sebuah kelas, Anda dapat, misalnya, mengambil Rectangle
darinya:
class Rectangle:
public Area<int>
{
// ...
};
Karena Area<int>
dan Area<char>
merupakan kelas yang berbeda, Anda bahkan dapat mengambil keduanya pada saat yang sama (namun saat mengakses anggota mereka, Anda harus berurusan dengan ambiguitas):
class Rectangle:
public Area<int>,
public Area<char>
{
// ...
};
Namun Anda harus menentukan kelas mana yang akan diturunkan saat Anda menentukan Rectangle
. Ini benar tidak peduli apakah kelas-kelas itu dihasilkan dari template atau tidak. Dua objek dari kelas yang sama tidak dapat memiliki hierarki pewarisan yang berbeda.
Yang bisa Anda lakukan adalah membuat Rectangle
template juga. Jika Anda menulis
template<typename T> class Rectangle:
public Area<T>
{
// ...
};
Anda memiliki template Rectangle
dari mana Anda bisa mendapatkan kelas Rectangle<int>
asal Area<int>
, dan kelas lain Rectangle<char>
asal Area<char>
.
Mungkin Anda ingin memiliki satu tipe Rectangle
sehingga Anda bisa meneruskan semua jenis Rectangle
ke fungsi yang sama (yang tidak perlu mengetahui tipe Area). Karena Rectangle<T>
kelas yang dibuat dengan membuat contoh template Rectangle
secara formal tidak bergantung satu sama lain, cara kerjanya tidak seperti itu. Namun Anda dapat menggunakan beberapa warisan di sini:
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);
}
Jika penting bahwa generik Anda Rectangle
diturunkan dari generik, Area
Anda juga dapat melakukan trik yang sama Area
:
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
};