如何自动包含目录中的所有标头

时间:2010-03-12 18:21:55

标签: c++ include

我正在阅读C ++书籍的练习。对于每个练习,我想最小化我必须编写的样板代码。我已经以某种方式设置了我的项目,但它似乎并不正确,并且需要进行太多更改。

现在我有一个main.cpp个文件,其中包含以下内容:

#include "e0614.h"
int main()
{
    E0614 ex;
    ex.solve();
}

每次我从练习中创建一个新类时,我都必须修改此文件以更改包含的标题的名称以及我正在实例化的类。

所以我的问题是:

  1. 我可以在目录中包含所有标题,这样至少我不需要更改#include行吗?
  2. 更好的是,我是否可以重写我的解决方案,以便我甚至不必触摸main.cpp,而没有一个文件包含每个练习的所有代码?

  3. 更新

    我最终通过脚本关注Poita_对生成main.cpp的建议。

    由于我使用的是IDE(Visual Studio),我希望将其与它集成,因此对其进行了一些研究。对于那些对如何感兴趣的人,请继续阅读(这是公平的,但并非完全,直截了当)。

    Visual Studio允许您通过工具使用外部工具 - > “外部工具”菜单,包含一组预定义的变量,例如$(ItemFileName),可以传递给工具。所以在这个例子中我使用了一个简单的批处理文件,它在Visual Studio中传递了当前所选文件的名称。

    要将该工具添加到工具栏,请右键单击工具栏,然后选择自定义 - >命令 - >工具,然后选择“外部命令X”并将其拖动到工具栏。用与您创建的工具对应的数字替换X.我的安装包含工具中列出的5个默认预先存在的工具 - >外部工具,所以我创建的是工具编号6.您必须弄清楚这个数字,因为它没有显示。然后,您可以为快捷方式指定一个图标(这是下面显示的BuildMain命令):

    alt text http://img691.imageshack.us/img691/4853/capturerg.png

10 个答案:

答案 0 :(得分:14)

  1. 没有。如果你想做的话,你必须把它们全部包括在内。

  2. 没有。至少,不是实际上会节省打字的方式。

  3. 当然,您可以编写一个脚本来为您创建main.cpp ...

答案 1 :(得分:9)

如果使用make构建代码,则应该可以执行此操作。

  

我可以在目录中包含所有标题,这样至少我不需要更改#include行吗?

将您的包含行更改为#include <all_headers.h>。现在,您可以让Makefile使用以下目标自动生成all_headers.h

all_headers.h:
    for i in `ls *.h`; do echo "#include <$i>" >>all_headers.h; done

确保在“干净”时删除all_headers.h

  

更好的是,我可以重写我的解决方案,以便我甚至不必触及main.cpp,   没有一个文件包含每个练习的所有代码吗?

如果您使用typedef抽象出您的课程,则可以执行此操作。在您的示例中,将您的班级名称从E0614更改为myClass(或其他内容)。现在,在上面for循环下方的Makefile中添加一行代表echo "typedef "$MY_TYPE" myClass;" >>all_headers.h。在构建程序时,使用类似make MY_TYPE=E0614的内容调用'make',你的typedef将自动填入你想要测试的类。

答案 2 :(得分:3)

如果您使用的是Unix系统,则可以使用指向最新练习的软链接。

ln -s e0615.h latest.h

并命名你的E级而不是E0614,当然

P.S。据我所知,你不能#include xxx*

答案 3 :(得分:1)

不要使用为每个练习修改的一个main.cpp。此解决方案使用make的内置规则,因此您只需键入make e0614,它将生成e0614.cpp,编译并链接它。您可以自定义每个 .cpp 文件(它们不会按照下面的说明重新生成)并保留所有历史记录,以便在您完成练习时参考,而不是在从一个文件移动到另一个文件时将其删除。下一个。 (您还应该使用源代码管理,例如Mercurial。)

生成文件

e%.cpp:
        ./gen_ex_cpp $@ > $@

您可以使用脚本生成样板代码,因为您不希望它也很乏味。这些脚本有几种选择 - 我使用各种语言,包括C ++,Python和shell--但下面的Python很简短,在这里应该简单明了。

示例生成脚本

#!/usr/bin/python
import sys
args = sys.argv[1:]
if not args:
  sys.exit("expected filename")
name = args.pop(0).partition(".")[0]
if args:
  sys.exit("unexpected args")
upper_name = name.upper()
print """
#include "%(name)s.hpp"
int main() {
  %(upper_name)s ex;
  ex.solve();
  return 0;
}
""" % locals()

答案 4 :(得分:0)

制作一个包含所需所有标题名称的主包含文件。

包含*是一个非常糟糕的主意,即使你可以。

答案 5 :(得分:0)

您可以使用连接来为类名使用条件编译。

// Somewhere in your other files
define CLASS_NUMBER E0614

// in main.cpp
#define ENTERCLASSNUMBER(num) \
##num## ex;

// in main()
ENTERCLASSNUMBER(CLASS_NUMBER)

虽然不知道包含。如上所述,脚本可能是最佳选择。

答案 6 :(得分:0)

编写一个makefile规则来将可执行文件的名称作为-DHEADERFILE = something参数传递给编译器应该不难。类似的东西:

%.exe : %.h %.cpp main.cpp
    gcc -o $< -DHEADER_FILE=$<F $>

OTOH,我不知道#include是否对文件名进行宏扩展。

答案 7 :(得分:0)

sed -i 's/\<\\([eE]\\)[0-9]+\\>/\19999/' main.cpp

将9999替换为所需的数字。可能有更好的方法。

答案 8 :(得分:0)

为什么不使用对象机制?

您可以使用Exemplar策略。

class BaseExercise
{
public:
  static bool Add(BaseExercise* b) { Collection().push_back(b); return true; }
  static size_t Solve() {
    size_t nbErrors = 0;
    for(collections_type::const_iterator it = Collection().begin(), end = Collection().end(); it != end; ++it)
      nbErrors += it->solve();
    return nbErrors;
  }

  size_t solve() const
  {
    try {
      this->solveImpl();
      return 0;
    } catch(std::exception& e) {
      std::cout << mName << " - end - " << e.what() << std::endl;
      return 1;
    }
  }
protected:
  explicit BaseExercise(const char* name): mName(name)
  {
  }
private:
  typedef std::vector<BaseExercise*> collection_type;
  static collection_type& Collection() { collection_type MCollection; return MCollection; }

  virtual void solveImpl() const = 0;

  const char* mName;
}; // class BaseExercise

template <class T>
class BaseExerciseT: public BaseExercise
{
protected:
  explicit BaseExerciseT(const char* b): BaseExercise(b) { 
    static bool MRegistered = BaseExercise::Add(this);
  }
};

好的,那就是基础。

// Exercise007.h
#include "baseExercise.h"

class Exercise007: public BaseExerciseT<Exercise007>
{
public:
  Exercise007(): BaseExerciseT<Exercise007>("Exercise007") {}
private:
  virtual void solveImpl() const { ... }
};

// Exercise007.cpp
Exercise007 gExemplar007;

主要

// main.cpp
#include "baseExercise.h"

int main(int argc, char* argv[])
{
  size_t nbErrors = BaseExercise::Solve();
  if (nbErrors) std::cout << nbErrors << " errors" << std::endl;
  return nbErrors;
}

在这里,你不需要任何脚本;)

答案 9 :(得分:-2)

试试这个: -

#ifndef a_h
#define a_h

#include <iostream>
#include <conio.h>
#incl....as many u like
class a{
f1();//leave it blank
int d;
}
#endif //save this as a.h

后 在你的主程序中包含这个cpp文件

#include "a.h"

...你的程序