我什么时候应该在C ++中使用typedef?

时间:2009-02-05 14:59:52

标签: c++ typedef

在我多年的C ++(MFC)编程中,我从未觉得需要使用typedef,所以我真的不知道它用于什么。我应该在哪里使用它?是否有使用typedef的首选实际情况?或者这更像是一个特定于C的关键字?

13 个答案:

答案 0 :(得分:83)

模板元编程

对于许多template metaprogramming任务,

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。请注意,模板元编程在库开发之外并不常用。

简化功能指针类型

typedef 有用为复杂的函数指针类型提供简短明确的别名:

typedef int (*my_callback_function_type)(int, double, std::string);

void RegisterCallback(my_callback_function_type fn) {
    ...
}

答案 1 :(得分:32)

在Bjarne的书中,他声明你可以使用typedef来处理具有不同整数大小的系统之间的可移植性问题。 (这是一种解释)

在sizeof(int)为4的机器上,您可以

typedef int int32;

然后在代码中的任何地方使用int32。当您转到sizeof(int)为2的C ++实现时,您只需更改typdef

typedef long int32;

并且您的程序仍然可以使用新的实现。

答案 2 :(得分:21)

使用函数指针

使用typedef隐藏函数指针声明

void (*p[10]) (void (*)() );

只有少数程序员可以告诉p是一个“指向返回void的函数的10个指针的数组,并且指向另一个返回void且不带参数的函数的指针。”繁琐的语法几乎难以辨认。但是,您可以使用typedef声明来大大简化它。首先,声明一个typedef,用于“指向返回void并且不带参数的函数的指针”,如下所示:

  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];

from

答案 3 :(得分:17)

只是提供一些例子说明: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 - 很简单:是真正的标题材料 - 或者至少是前向标题。无论如何,你确实需要shared_ptr的前向声明,并且它声明的一个优点是可以安全地使用前向decl。

换句话说:如果有一个shared_ptr,你可能只应该通过shared_ptr使用该类型,所以分离声明没有多大意义。

(是的,xyzfwd.h很痛苦。我只在热点使用它们 - 知道热点很难识别。责怪C ++编译+链接模型......)

容器typedef我通常在声明容器变量的地方使用 - 例如本地var用于本地var,作为类成员,当实际容器实例是类成员时。如果实际容器类型是实现细节,则这很有效 - 不会产生额外的依赖性。

如果它们成为特定接口的一部分,它们将与它们所使用的接口一起声明,例如。

// FrobozMangler.h
#include "Froboz.h"
typedef std::map<int, Froboz> tFrobozMap;
void Mangle(tFrobozMap const & frobozzes); 

当类型是不同接口之间的绑定元素时,这会产生问题 - 即多个标头需要相同的类型。一些解决方案:

  • 将其与所包含的类型一起声明 (适用于经常用于此类型的容器)
  • 将它们移至单独的标题
  • 移动到单独的标头,并使其成为一个数据类,其中实际容器再次是实现细节

我同意后者不是那么好,只有当我遇到麻烦时才会使用它们(不是主动)。

答案 4 :(得分:5)

typedef在很多情况下都很有用。

基本上它允许您为类型创建别名。当/如果必须更改类型时,其余代码可以保持不变(当然这取决于代码)。 例如,假设你想在c ++向量上使用它

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也可以节省你的时间,而这些数据结构很难编写(并且难以阅读)

答案 5 :(得分:5)

使用typedef的一个好理由是,某些内容的类型可能会发生变化。例如,假设现在,16位整数可以用于索引某些数据集,因为在可预见的将来,您将拥有少于65535个项目,并且空间限制很重要或者您需要良好的缓存性能。但是,如果您需要在超过65535项的数据集上使用程序,则希望能够轻松切换到更宽的整数。使用typedef,您只需在一个地方更改它。

答案 6 :(得分:4)

typedef不仅允许复杂类型的别名,而且还为您提供了记录类型的自然位置。我有时会将它用于记录目的。

有时候我会使用一个字节数组。现在,一个字节数组可能意味着很多事情。 typedef可以将我的字节数组定义为“hash32”或“fileContent”,以使我的代码更具可读性。

答案 7 :(得分:2)

typedef的实际使用:

  • 为冗长的模板类型提供友好的别名
  • 为函数指针类型提供友好的别名
  • 为类型提供本地标签,例如:

    template<class _T> class A
    {
        typedef _T T;
    };
    
    template<class _T> class B
    {
        void doStuff( _T::T _value );
    };
    

答案 8 :(得分:2)

当我们想要启用一种容器无关代码(但不完全是!)时,还有另一个使用typedef的用例

让我们说你上课了:

Class CustomerList{

public:
    //some function
private:
    typedef list<Customer> CustomerContainer;
    typedef CustomerContainer::iterator Cciterator;
};

上面的代码使用typedef封装了内部容器实现,即使将来列表容器需要更改为vector或者deque,CustomerList类的用户也不需要担心确切的容器实现。

因此,typedef封装并在某种程度上帮助我们编写Container Independent代码

答案 9 :(得分:0)

每当它使源更清晰或更好阅读时。

我在C#中使用了一些typedef来表示泛型/模板。 “NodeMapping”更好地阅读/使用并理解很多“Dictionary&lt; string,XmlNode&gt;”。恕我直言。所以我推荐它用于模板。

答案 10 :(得分:0)

Typedef允许您的课程具有灵活性。如果要更改程序中的数据类型,则无需更改多个位置,只需更改一个位置即可。

typedef <datatype example  int or double> value_type

您可以使用nay名称而不是value_type,但value_type通常是标准名称。

所以你可以使用像

这样的typedef
value_type i=0;     //same as a int or double i=0; 

答案 11 :(得分:0)

typedef 的 1 个实际示例是 size_t。它保证足够大以包含主机系统可以处理的最大对象的大小。最大允许大小取决于编译器;如果编译器是 32 位,那么它只是 typedefunsigned int,但如果编译器是 64 位,那么它就是 typedefunsigned long longsize_t 数据类型从不为负。

答案 12 :(得分:-2)

...而且你不需要为枚举或结构提供Typedef。

或者你呢?

typedef enum { c1, c2 } tMyEnum;
typedef struct { int i; double d; } tMyStruct;

可以更好地写成

enum tMyEnum { c1, c2 }
struct  tMyStruct { int i; double d; };

这是对的吗?那怎么样?