我对C很新,但我的理解是#include语句基本上只是将#included文件的内容转储到该语句的位置.这意味着如果我的头文件中有一些’#include’和’using’语句,我的实现文件只能#include头文件,编译器不介意我不重复其他语句.
那人呢呢?
我主要担心的是,如果我不重复’#include’,’using’,以及’typedef'(现在我想到它)语句,它会从使用它的文件中取出该信息,可能导致混乱.
我现在只是处理小型项目,它不会真正导致任何问题,但我可以想象,在有更多人工作的大型项目中,它可能成为一个重要问题.
一个例子如下:
更新:我的’Unit’函数原型在它们的返回类型和参数中有字符串,ostream和StringSet – 我没有在我的头文件中包含任何只在实现文件中使用的内容.
//Unit.h #include <string> #include <ostream> #include "StringSet.h" using std::string; using std::ostream; class Unit { public: //public members with string,ostream and StringSet //in their return values/parameter lists private: //private members //unrelated side-question: should private members //even be included in the header file? } ; //Unit.cpp #include "Unit.h" //The following are all redundant from a compiler perspective: #include <string> #include <ostream> #include "StringSet.h" using std::string; using std::ostream; //implementation goes here
解决方法
using-directive(using namespace std;)不应该驻留在头文件中,除非它包含在一个函数中.这是不好的做法.标头的每个用户都不太可能希望对给定命名空间中的所有内容进行非限定查找;包含不相关的标头可能会导致意外的歧义和编译失败.就个人而言,我在相同的推理中避免使用函数内部的使用指令,但这通常被认为危害较小.
应谨慎使用类型别名(通过typedef std :: string string;或使用string = std :: string;).类型定义具有意义,因此您永远不应重新声明它.例如,这是一个错误:
typedef int myint; typedef float myint;
因为类型冲突.
using声明(使用std :: string;或使用std :: memcpy;)使得符号可以访问unqualified name lookup.当获得argument-dependent lookup正确时这非常有用,除非你正在编写一个库,这通常无关紧要.根据您是否引入类型或功能,建议会有所不同.考虑使用与类型别名相同的类型的声明:在同一名称下有多个定义是没有意义的.对于函数,您所做的只是扩展重载决策以包含更多内容(尽管通常没有必要).
// Finding multiple operator<< functions makes sense using std::operator<<; using mylib::operator<<; // Finding multiple string classes does not make sense using std::string; using mylib::string;
要重复#include,您应该考虑是否确实需要首先在头文件中包含该文件.也许forward declaration符合您的需求.