在我多年的 C + + (MFC)编程生涯中,我从未觉得有必要使用 typedef,所以我真的不知道它是用来做什么的。我应该在哪里使用它?是否存在使用 typedef为首选的实际情况?或者这真的是一个 C 特定的关键字?
typedef
Typedef 的实际用法:
为类型提供本地标签,例如:
template<class _T> class A { typedef _T T; }; template<class _T> class B { void doStuff( _T::T _value ); };
对于许多 模板超编程任务,typedef是 有需要——每当一个类被视为“编译时类型函数”时,typedef就被用作“编译时类型值”来获得结果类型。例如,考虑一个将指针类型转换为基类型的简单元函数:
template<typename T> struct strip_pointer_from; template<typename T> struct strip_pointer_from<T*> { // Partial specialisation for pointer types typedef T type; };
示例: 类型表达式 strip_pointer_from<double*>::type的计算结果为 double。请注意,模板超编程在图书馆发展之外并不常用。
strip_pointer_from<double*>::type
double
typedef是 很有帮助,为复杂的函数指针类型提供一个简短、尖锐的别名:
typedef int (*my_callback_function_type)(int, double, std::string); void RegisterCallback(my_callback_function_type fn) { ... }
只要它使源代码更清晰或更好地阅读。
我在 C # 中对泛型/模板使用 kind of typedef。“ NodeMapping”比“ Dictionary < string,XmlNode >”更适合阅读/使用和理解。恕我直言。因此,我建议将其用于模板。
和函数指针一起使用
用 typedef 隐藏函数指针声明
void (*p[10]) (void (*)() );
只有少数程序员能说出 p 是一个“由10个指向返回 void 的函数的指针组成的数组,并且带有一个指向另一个返回 void 且不带参数的函数的指针。”这种繁琐的语法几乎无法破译。但是,可以通过使用 typedef 声明来大大简化它。首先,为“返回 void 且不接受任何参数的函数的指针”声明 typedef,如下所示:
typedef void (*pfv)();
接下来,根据我们之前声明的 typedef,为“返回 void 并获取 pfv 的函数的指针”声明另一个 typedef:
typedef void (*pf_taking_pfv) (pfv);
现在我们已经创建了 pf _ taking _ pfv typedef 作为笨拙的“指向返回 void 并接受 pfv 的函数的指针”的同义词,声明一个包含10个这样的指针的数组简直是小菜一碟:
pf_taking_pfv p[10];
由 开始
在 Bjarne 的书中,他指出您可以使用 typedef 来处理具有不同整数大小的系统之间的可移植性问题。(这是一个解释)
在 sizeof(int)为4的机器上,你可以
sizeof(int)
typedef int int32;
然后在代码的任何地方使用 int32。当您转移到 C + + 的实现时,其中 sizeof(int)为2,那么您只需更改 typdef即可
int32
typdef
typedef long int32;
你的程序仍然会在新的实现上工作。
Typedef 在很多情况下都很有用。
基本上,它允许您为类型创建别名。当/如果您必须更改类型时,代码的其余部分可以保持不变(当然,这取决于代码)。 例如,假设您想对一个 c + + 向量进行 ITER
vector<int> v; ... for(vector<int>::const_iterator i = v->begin(); i != v.end(); i++) { // Stuff here }
在将来,您可能会考虑使用列表来更改向量,因为您必须对它执行的操作类型。如果没有 typedef,则必须更改代码中出现的所有向量。 但是如果你这样写:
typedef vector<int> my_vect; my_vect v; ... for(my_vect::const_iterator i = v->begin(); i != v.end(); i++) { // Stuff here }
现在你只需要改变一行代码(即从“ typedef vector<int> my_vect”到“ typedef list<int> my_vect”) ,一切就都可以正常工作了。
typedef vector<int> my_vect
typedef list<int> my_vect
Typedef 还可以节省您的时间,因为复杂的数据结构写起来很长(而且很难读)
使用 typedef 的一个很好的理由是,某些内容的类型可能会发生变化。例如,假设目前,16位 int 可以用于索引某些数据集,因为在可预见的未来,您将只有少于65535个条目,并且空间限制很大,或者您需要良好的缓存性能。但是,如果您需要在一个包含超过65535个项目的数据集上使用程序,那么您希望能够轻松地切换到一个更广泛的整数。使用 typedef,您只需要在一个地方更改它。
只是提供一些例子的东西说: STL 容器。
typedef std::map<int,Froboz> tFrobozMap; tFrobozMap frobozzes; ... for(tFrobozMap::iterator it=frobozzes.begin(); it!=map.end(); ++it) { ... }
甚至使用类似以下的 typedef 也是很正常的
typedef tFrobozMap::iterator tFrobozMapIter; typedef tFrobozMap::const_iterator tFrobozMapCIter;
另一个例子: 使用共享指针:
class Froboz; typedef boost::shared_ptr<Froboz> FrobozPtr;
[更新] 根据评论-把它们放在哪里?
最后一个例子-使用 shared_ptr-是很容易的: 是真正的标题材料-或者至少是一个向前的标题。无论如何,您都需要 share _ ptr 的前向声明,它的一个优点是可以安全地使用 forward decl。
shared_ptr
换句话说: 如果存在 share _ ptr,那么您可能只应该通过 share _ ptr 使用该类型,因此分隔声明没有多大意义。
(是的,xyzfwd.h 是一个痛苦。我只会在热点地区使用它们——因为我知道热点地区很难识别。要怪就怪 C + + 编译 + 链接模型...)
我通常在声明容器变量时使用 Container typedef-例如,在本地声明一个局部变量,在实际的容器实例是一个类成员时作为类成员。如果实际的容器类型是一个实现细节,那么这种方法可以很好地工作——不会产生额外的依赖性。
如果它们成为 特别接口的一部分,它们将与使用它们的接口一起声明,例如。
// FrobozMangler.h #include "Froboz.h" typedef std::map<int, Froboz> tFrobozMap; void Mangle(tFrobozMap const & frobozzes);
当类型是不同接口之间的绑定元素时,就会出现问题——也就是说,多个头需要相同的类型。一些解决方案:
我同意后两者都不是很好,我只会在遇到麻烦的时候使用它们(不会主动使用)。
枚举或结构不需要 Typedef。
是吗?
typedef enum { c1, c2 } tMyEnum; typedef struct { int i; double d; } tMyStruct;
可以写得更好
enum tMyEnum { c1, c2 } struct tMyStruct { int i; double d; };
对吗,那 C 呢?
typedef不仅允许为复杂类型提供别名,而且还为记录类型提供了一个自然的位置。我有时用它来记录文档。
也有时候我使用字节数组。现在,字节数组可能意味着很多东西。typedef可以方便地将字节数组定义为“ hash32”或“ fileContent”,从而使代码更具可读性。
当我们想要启用一种 集装箱独立代码(但不是完全启用)时,使用 typedef 还有另外一种用例
假设你有品位:
Class CustomerList{ public: //some function private: typedef list<Customer> CustomerContainer; typedef CustomerContainer::iterator Cciterator; };
上面的代码使用 typedef 封装了内部容器实现,即使将来列表容器需要更改为 Vector 或 deque,CustomerList 类的用户也不需要担心确切的容器实现。
因此,typedef 封装并在一定程度上帮助我们编写容器独立的代码
Typedef 允许类的灵活性。如果要更改程序中的数据类型,则不需要更改多个位置,只需更改一个事件。
typedef <datatype example int or double> value_type
您可以使用 nay 而不是 value_type,但是 value_type通常是标准名称。
value_type
所以你可以像这样使用 typedef
value_type i=0; //same as a int or double i=0;
typedef的一个实际例子是 size_t。它保证足够大以容纳主机系统能够处理的最大对象的大小。最大允许大小取决于编译器; 如果编译器是32位,那么对于 unsigned int来说它只是一个 typedef,但是如果编译器是64位,那么对于 unsigned long long来说它就是一个 typedef。size_t数据类型永远不会是负数。
size_t
unsigned int
unsigned long long