Szablony C++ są dobrze znane z tego, że przyjmują typy jako argumenty, ale można je również sparametryzować w stosunku do innych typów danych. Na przykład, można templatize klasę na liczbę całkowitą, jak pokazano poniżej:
template <typename T, unsigned int N> class Array {
private:
T array[N];
public:
/* ... */
};
Szablony mogą być również programowane przez wskaźniki, o ile wskaźnik spełnia określone kryteria (na przykład, to musi ocenić na adres czegoś, co można określić podczas kompilacji).Na przykład, jest to całkowicie legalne:
template <int* Pointer> class ThisIsLegal {
public:
void doSomething() {
*Pointer = 137;
}
};
W kodzie, szablon jest parametryzowane przez wskaźnik do klasy-członka. Wskaźnik do klasy jest podobny do wskaźnika, ponieważ pośrednio odwołuje się do jakiegoś obiektu. Jednak zamiast wskazywać na obiekt, wskazuje on pole w klasie. Pomysł polega na tym, że można wyłuskać wskaźnik do klasy członka względem jakiegoś obiektu, aby wybrać to pole z klasy. Oto prosty przykład wskaźników-do-klasowej użytkownika:
struct MyStruct {
int x, y;
};
int main() {
MyStruct ms;
ms.x = 137;
ms.y = 42;
int MyStruct::* ptr; // Declare a pointer to a class member.
ptr = &MyStruct::x; // Now points to the field 'x'
ms.*ptr = 0; // Set the 'x' field of ms to be zero.
}
zauważyć, że składnia deklarowania wskaźnik do klasy członek jest
Type ContainingClass::* pointerName;
Tak więc w powyższym kodzie int MyStruct::* ptr
pomocą „. wskaźnik do int
wnętrza MyStruct
klasa
w kodzie, które zostały zaksięgowane, deklaracja szablon brzmi tak:
template <
class PropObject,
class PropType,
PropType PropObject::* Prop
>
class PropReader
Zobaczmy, co to oznacza. Dwa pierwsze obiekty argumentu szablonu, których własność ma zostać odczytana, i PropType
, typ tej właściwości. "Ostatnim argumentem do szablonu jest element wskaźnika do klasy o nazwie Prop
, który wskazuje wewnątrz pola na wartość . wpisz PropType
na przykład, można utworzyć wystąpienia tego szablonu z MyStruct
jak ten:.
PropReader<MyStruct, int, &MyStruct::x> myPropReader;
teraz zobaczmy co reszta kodu jest ciało tej klasy szablonu jest przedrukowany tutaj.
void print(Object& o)
{
PropObject& po = static_cast<PropObject &>(o);
PropType& t = po.*Prop;
cout << t << "\n";
}
Niektóre z nich można dość łatwo odczytać. dla tej funkcji jest odniesieniem do Object
o nazwie o
, a ostatnia linia drukuje niektóre pola. Te dwie linie są trudne:
PropObject& po = static_cast<PropObject &>(o);
PropType& t = po.*Prop;
Ta pierwsza linia jest typecast że mówi „spróbuj rzucić argument o
do odniesienia typu PropObject
Pomysł, zgaduję, że Object
pewne klasy bazowej. wielu różnych obiektów .Parametrem tej funkcji jest zwykły Object
, a ta obsada próbuje przekonwertować ją na coś odpowiedniego typu (przypomnij, że PropObject
jest szablonowym argumentem mówiącym o typie obiektu). to używa static_cast
, jeśli konwersja nie jest zdefiniowana (na przykład próbujesz utworzyć instancję szablonu przez int
lub vector<string>
), kod nie zostanie skompilowany. e, kod ufa, że rzutowanie jest bezpieczne, a następnie otrzymuje odniesienie typu PropObject
do tego, do czego odnosi się parametr.
Wreszcie ostatnia linia jest
PropType& t = po.*Prop;
używa wyłuskiwania składni wskaźnik do klasy-członka wspomniałem wcześniej, aby powiedzieć „wybierz pole wskazał przez Prop
(argument szablonu), a następnie przechowywać odniesienie do niego o nazwie t
.
Więc, krótko mówiąc, szablon
- prosi o rodzaju jakiegoś przedmiotu.
- Pyta o typ pola w tym obiekcie.
- Pyta o wskaźnik do pola w tym obiekcie.
- Udostępnia funkcję
print
, która w przypadku obiektu próbuje wydrukować to pole.
Whew! To było trudne! Mam nadzieję że to pomoże!
To była niesamowita odpowiedź templatetypedef .. nic dziwnego, że masz tę nazwę użytkownika :) – cgcoder