类型萃取是实现不同类型数据面对同一函数实现不同的操作,它与类封装的区别是:并不用知道所调用的对象是什么类型,类型萃取是编译后知道类型,先实现;而类的封装则是先定义类型,后实现方法。
类型分为基本类型(POD),和自定义类型。
在这里用模板的特化实现其编程思想:
以memcpy为例,当拷贝的是基本类型(POD)时,只用拷贝所传递指针上的数据,如果是string类型,则需要在堆上开辟空间,所传递的指针如果被直接复制,则有可能(vs下的string类型的实现原理是若字符串不长则以数组保存,若字符串过长,则通过指针在堆上开辟空间进行保存)出现同一地址,析构两次,出现错误。
程序:
#include<iostream>
using namespace std;
#include<string>
struct __TrueType
{
static bool Get()
{
return true;
}
};
struct __FalseType
{
static bool Get()
{
return false;
}
};
template <class T>
struct TypeTraits//traits为特性
{
typedef __FalseType __IsPODType;
};
template <>
struct TypeTraits< bool>
{
typedef __TrueType __IsPODType;
};
template <>
struct TypeTraits< char>
{
typedef __TrueType __IsPODType;
};
template <>
struct TypeTraits< unsigned char >
{
typedef __TrueType __IsPODType;
};
template <>
struct TypeTraits< short>
{
typedef __TrueType __IsPODType;
};
template <>
struct TypeTraits< unsigned short >
{
typedef __TrueType __IsPODType;
};
template <>
struct TypeTraits<int>
{
typedef __TrueType __IsPODType;
};
template<class T>
void _Memcpy(T& dest, const T& src, size_t size, __TrueType) //基本类型
{
cout << "IsPOD::" << typeid(T).name() << endl;
memcpy(dest, src, sizeof(T)*size);
}
template<class T>
void _Memcpy(T& dest, const T& src, size_t size, __FalseType)
{
cout << "IsNotPOD::" << typeid(T).name() << endl;
for (int i = 0; i < size; i++)
{
dest[i] = src[i];
}
}
template<class T>
class SeqList
{
public:
SeqList()
:_size(0)
, _capacity(0)
, _array(NULL)
{}
SeqList<T>(const SeqList<T>& s)
{
_array = new T[s._size];
if (TypeTraits <T>::__IsPODType().Get())
{
_Memcpy(_array, s._array, s._size, TypeTraits<T>::__IsPODType());
}
else
{
_Memcpy(_array, s._array, s._size, TypeTraits<T>::__IsPODType());
}
swap(_size, s._size);
swap(_capacity, s._capacity);
}
SeqList<T>& operator= (SeqList<T> s)
{
swap(_array, s._array);
swap(_size, s._size);
swap(_capacity, s._capacity);
}
~SeqList()
{
if (_array)
{
delete[] _array;
_array = NULL;
}
}
void _CheckCapacity(size_t n)
{
if (n > _capacity)
{
_capacity = 2 * _capacity + 3;
T* tmp = new T[_capacity];
if (_array != NULL)
{
if (TypeTraits <T>::__IsPODType().Get())
{
_Memcpy(tmp, _array, _size, TypeTraits <T>::__IsPODType());
}
else
{
_Memcpy(tmp, _array, _size, TypeTraits <T>::__IsPODType());
}
}
delete[] _array;
_array = NULL;
_array = tmp;
}
}
void PushBack(const T& x);//尾插
void PopBack();//尾出
void PrintSeqList();//打印链表
private:
size_t _size;
size_t _capacity;
T* _array;
};
template<class T>
void SeqList<T>::PushBack(const T& x)
{
_CheckCapacity(_size + 1);
_array[_size++] = x;
}
template<class T>
void SeqList<T>::PopBack()
{
if (_size == 0)
{
return;
}
else
{
--_size;
}
}
template<class T>
void SeqList<T>::PrintSeqList()
{
for (int i = 0; i < _size; i++)
{
cout << _array[i] << " ";
}
cout << endl;
}
//int的测试函数
//void Test()
//{
// SeqList<int> s1;
// s1.PushBack(1);
// s1.PushBack(2);
// s1.PushBack(3);
// s1.PushBack(4);
// s1.PushBack(5);
// s1.PrintSeqList();
// s1.PrintSeqList();
//}
//string的测试函数
void Test()
{
SeqList<string> s2;
s2.PushBack("Hello");
s2.PushBack("yaoyao! ");
s2.PrintSeqList();
s2.PrintSeqList();
}
int main()
{
Test();
system("pause");
return 0;
}
运行结果:
Hello yaoyao!
Hello yaoyao!
请按任意键继续. . .
本文出自 “岩枭” 博客,请务必保留此出处http://yaoyaolx.blog.51cto.com/10732111/1765956
原文地址:http://yaoyaolx.blog.51cto.com/10732111/1765956