C++:我应该使用'typedef'还是'using namespace'?

40

我正在编写一个有多个依赖模块的库。当我包含来自另一个模块的文件时,应该使用以下方式解析命名空间:


using namespace project1::namespace1;
class1 obj;

或者

typedef project1::namespace1::class1 class1;
class1 obj;

每种方法的优缺点是什么?我在某个地方读到说我们应该在.H文件中使用typedef,而在.C文件中使用using,这样做是否可行?

我遇到的一个问题是,如果我在第三个模块中同时包含原始类和带有'typedef'的类,它会导致命名空间的歧义。


18
一种替代方案是使用 project1::namespace1::class1; - hmjd
1
“这取决于情况。” 这里没有一个正确的答案。 - bmargulies
@bmargulies 谢谢。您能否详细说明一下? - vidit
C++ 没有一个连贯的设计结构,因为它是在 C 的基础上逐渐添加自己的特性。所以它既有 'using' 也有 'typedef',对于一个单一项目来说,它们的实用性很难区分。 - bmargulies
我们应该在 .H 文件中使用 'typedef',在 .C 文件中使用 'using'。我不同意在 .h 文件中使用整个命名空间,因为这意味着您正在向全局命名空间中添加 .c 文件可能不希望的内容。.c 文件是它自己的编译单元,可以随心所欲。但是,我认为 hmjd 的解决方案比 typedef 更好。 - Rup
4个回答

76

你提到的两个选项并不等同。以下是其中一个选项:

using namespace project1::namespace1;

导入命名空间会将所有内容都引入进来,使得冲突概率增加而且没有太多控制权。我只看到了缺点,没有优点。

但是,你不需要使用typedef来引入单个符号,可以使用

using project1::namespace1::class1;

无论您使用这个还是typedef,都不会有太大的区别。但要记住,typedef仅限于类型和枚举,而using可以引用值、函数等:

namespace X {
  const int x{42};
  enum Fruit{Apple, Pear};
}

using X::x; // OK
typedef X::x xx; // Error! 'x' in namespace 'X' does not name a type

所以这两个表达式并不完全等价。


1
听起来不错。这也可以避免问题中提到的歧义问题。 - vidit

8

不应该仅为了让名字更容易打,而在头文件中使用 usingtypedef

在源文件中,由您决定。通常建议完整书写名称,这样可以非常清楚地表达您的意思。如果命名空间太长,可以使用命名空间别名来减少混乱,但仍保持含义清晰:namespace ns = project1::namespace1;

不管怎样,如果要将符号导入全局命名空间,请使用 using,而不是 typedeftypedef 主要用于为类型命名不同的名称,往往因为它是模板而使用 - 例如,my_map 而不是 std::map<std::string, my_type>,这仍然清晰明了,但打起来更方便。

另外,请参见此问题:为什么在 C++ 中被认为 "using namespace std" 是一种不好的做法?


6
在头文件中永远不要使用typedef?真的吗?这是将几个类型定义为应用程序中其他部分要使用的标准做法,可以将它们全部放在单个头文件中。例如,在libsdl中使用的Uint8和Qt 4中的quint16。 - SigTerm
3
@SigTerm: parkovski反对在头文件中缩写传入类型以供本地使用。使用typedef定义您的公开API是完全不同且可以的。 - David Schmitt
6
@DavidSchmitt:你提到的两种“使用模式”是相同的,代表着同一件事情——你创建一个中央头文件,并在其中使用声明的类型。无论是用于“导入”还是“导出”都是无关紧要的。parkovski的建议听起来不合理,因为在*.h文件中有许多可以放置typedef的地方——你可以将其封装在类、命名空间等中,这是安全的。此外,typedef并不会造成混乱。因此,无论如何,“*.h中不允许typedef”听起来像是对编码风格的毫无意义的人为限制——没有任何好处,所以不应该使用这个规则。 - SigTerm
@SigTerm 我认为你没有读完那句话。标准C在头文件中有大量的typedef非常有用(例如size_tptrdiff_t)。区别在于它们是API的一部分,服务于特定的目的,而不仅仅是某人“因为我不喜欢打字”而使用的快捷方式。 - parkovski

6
最简单的方法是不使用这些方法之一 - 只需编写new project1::namespace1::class1()

也许是这样,但有时会变得有些啰嗦,不是吗? - William Payne

3

使用 using project1::namespace1::class1

或者,您可以在本地范围内限制使用名称空间,以方便自己并避免污染全局名称空间。

void function()
{
    using namespace project1::namespace1;

    class1 obj;

    ...
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接