以上两个定义内容只有里面的类型不同,那么为什么不忽略类型的差异,定义通用的容器?于是类模板出现: 类模板的定义和使用: #ifndef ARRAY_H #define ARRAY_H #include<assert.h>// for assert() template <classT> // This is a template class, the user will provide the data type for T classArray { private: int m_length;//注意这里可以指定具体类型; T *m_data; public: Array() { m_length = 0; m_data = nullptr; } Array(int length) { m_data = new T[length]; m_length = length; } ~Array() { delete[] m_data; } voidErase() { delete[] m_data; // We need to make sure we set m_data to 0 here, otherwise it will // be left pointing at deallocated memory! m_data = nullptr; m_length = 0; } T& operator[](int index) { assert(index >= 0 && index < m_length); return m_data[index]; } // The length of the array is always an integer // It does not depend on the data type of the array intgetLength(); // templated getLength() function defined below }; template <typename T> // member functions defined outside the class need their own template declaration int Array<T>::getLength() { return m_length; } // note class name is Array<T>, not Array #endif 使用: #include<iostream> #include"Array.h" intmain() { Array<int> intArray(12); Array<double> doubleArray(12); for (int count = 0; count < intArray.getLength(); ++count) { intArray[count] = count; doubleArray[count] = count + 0.5; } for (int count = intArray.getLength()-1; count >= 0; --count) std::cout << intArray[count] << "\t" << doubleArray[count] << '\n'; return0; }
```cpp 针对上述问题,有几种处理方式: 1)把定义全放在.h头文件 2)把 rename Array.cpp to Array.inl (.inl stands forinline), and then include Array.inl from the bottom of the Array.h header. That yields the same result as putting all the code in the header, but helps keep things a little cleaner. 3)在main中include所有: // Ensure the full Array template definition can be seen #include"Array.h" #include"Array.cpp"// we're breaking best practices here, but only in this one place // #include other .h and .cpp template definitions you need here templateclassArray<int>; // Explicitly instantiate template Array<int> templateclassArray<double>; // Explicitly instantiate template Array<double> // instantiate other templates here
模板类参数可以是无类型,即某种特定的类型: A value that has an integral type or enumeration A pointer or reference to a classobject A pointer or reference to a function A pointer or reference to a classmember function std::nullptr_t 例子: #include<iostream> template <classT, int size> // size is the non-type parameter classStaticArray { private: // The non-type parameter controls the size of the array T m_array[size]; public: T* getArray(); T& operator[](int index) { return m_array[index]; } }; // Showing how a function for a class with a non-type parameter is defined outside of the class template <classT, int size> T* StaticArray<T, size>::getArray() { return m_array; } intmain() { // declare an integer array with room for 12 integers StaticArray<int, 12> intArray; // Fill it up in order, then print it backwards for (int count=0; count < 12; ++count) intArray[count] = count; for (int count=11; count >= 0; --count) std::cout << intArray[count] << " "; std::cout << '\n'; // declare a double buffer with room for 4 doubles StaticArray<double, 4> doubleArray; for (int count=0; count < 4; ++count) doubleArray[count] = 4.4 + 0.1*count; for (int count=0; count < 4; ++count) std::cout << doubleArray[count] << ' '; return0; }
特化bool: template <> // the following is a template class with no templated parameters classStorage8<bool> // we're specializing Storage8 for bool { // What follows is just standard class implementation details private: unsignedchar m_data; public: Storage8() : m_data(0) { } voidset(int index, bool value) { // Figure out which bit we're setting/unsetting // This will put a 1 in the bit we're interested in turning on/off unsignedchar mask = 1 << index; if (value) // If we're setting a bit m_data |= mask; // Use bitwise-or to turn that bit on else// if we're turning a bit off m_data &= ~mask; // bitwise-and the inverse mask to turn that bit off } boolget(int index) { // Figure out which bit we're getting unsignedchar mask = 1 << index; // bitwise-and to get the value of the bit we're interested in // Then implicit cast to boolean return (m_data & mask); } }; intmain() { // Define a Storage8 for integers (instantiates Storage8<T>, where T = int) Storage8<int> intStorage; for (int count=0; count<8; ++count) intStorage.set(count, count); for (int count=0; count<8; ++count) std::cout << intStorage.get(count) << '\n'; // Define a Storage8 for bool (instantiates Storage8<bool> specialization) Storage8<bool> boolStorage; for (int count=0; count<8; ++count) boolStorage.set(count, count & 3); for (int count=0; count<8; ++count) std::cout << (boolStorage.get(count) ? "true" : "false") << '\n'; return0; }