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