C++条件包含文件运行时

问题描述:

我正在研究用C++编码的游戏,并且希望能够在运行时更改语言。目前,该语言是由包含一个头文件(其中有语言定义),像这样在编译时选择:C++条件包含文件运行时

#include "lan_eng.h" 

因此,游戏不允许一旦客户端已编译改变的语言。我的问题是,如果有一种方法可以在运行时有条件地包含文件?我是新的C++,所以起初我在想,我可以做这样的事情:

#define DEF_LANGUAGE_ENG 
//#define DEF_LANGUAGE_DEN 

#ifdef DEF_LANGUAGE_ENG 

    #include "lan_eng.h" 

#endif 

#ifdef DEF_LANGUAGE_DEN 

    #include "lan_den.h" 

#endif 

肯定,使得它更容易维护,但问题是,我相信它只能在编译时。我希望能够将所选语言存储在变量中(在运行时更改),然后使用该变量选择要包含哪个头文件。有没有办法做到这一点与头文件,或者我会被迫做一个类?

我希望这不是一个愚蠢的问题;我的搜索没有给我我期待的结果。

在此先感谢!

+1

预处理器是构建过程的第一个阶段。所以,AFAIK,运行时包含头文件可能是不可能的。 – Mahesh

由于只在编译期间对它们进行评估,因此不能在运行时更改#include。

你可以做什么,而不是,有“语言表”。您可以构建一个您在运行时参考的系统,或者您可以在您想要更改语言时读取和存储多个文本文档(如.xml文件)。这样做也可以让您的应用程序在将来被软件用户扩展,因为它不会被硬编码。

如果以这种方式进行设计,您可以将所有“语言表”保存在一个文件夹中,然后让程序检查该文件夹中是否有所有可用的语言表。这将允许用户也添加语言到您的程序。

你基本上需要做的是创建一个字符串表,它可以作为硬编码方法的一部分,或作为更动态方法的一部分(作为语言表提到)。

你不能这样做#include,这只是编译时间。更具体地说,这只是预处理器,这是在编译之前发生的。

为了获得运行时变化,你必须将你的翻译移动到一个文本文件(类似xml的东西,但纯文本也可以),并建立一个系统在启动时加载文件来填充字符串在需要翻译的代码中。

这也意味着您的所有字符串将在启动时动态调整大小,因此代码的初始化时间将增加。但有时候这就是灵活性的代价。

也许我已经想到的最简单的方法是:

struct language { 
    virtual str::string greeting() =0; 
    virtual str::string greeting(const std::string& name) =0; 
    virtual str::string goodbye() =0; 
    virtual ~language() {} 
}; 
struct English_language { 
    virtual str::string greeting() {return "Hello";} 
    virtual str::string greeting(const std::string& name) {return "Hello "+name;} 
    virtual str::string goodbye() {return "Goodbye";} 
} English; 
struct German_language { 
    virtual str::string greeting() {return "Hallo";} 
    virtual str::string greeting(const std::string& name) {return name+" Hallo";} 
    virtual str::string goodbye() {return "Auf Wiedersehen";} 
} German; 
language* CurLanguage = &English; 

int main() { 
    std::cout << CurLanguage->greeting("Steve") << '\n'; 
    CurLanguage = &German; 
    std::cout << CurLanguage->goodbye() << '\n'; 
} 

[编辑]我从头重写了它,因为我意识到纯虚函数是错误在编译的时候,如果你错过一个句子的方式,使维护更简单。这个版本还能够整齐地处理变量(日期,名称,时间,数字等)。这个概念是基于我们在我的工作中使用的,用于20多种语言的2900多个短语/句子。

+0

不幸的是,有很多阶段需要翻译,所以这个解决方案不适合。正如你所说,这对小项目很有好处。谢谢你的想法。 :) – Andy0708

在编译前实际发生预处理(#include,#ifdef,#define等)。您可以将预处理视为文本替换,其输出是提供给编译器的源代码。 #defines等在你的程序中占用了一个独立的变量名称空间,当你编译程序的时候,所有这一切都是成立的。换句话说,你所要求的是不可能的。

为了更好地理解这一点,请查看您的编译器选项并查找可让您保留预处理输出的选项。

你需要做的是改变你的字符串处理的工作方式。不需要在编译时更改字符串,而需要在运行时执行某些操作。

检查您的平台 - 在大多数平台上都有用于本地化的API。不过,它们因平台而异,所以如果您正在制作跨平台应用程序,那么您可能必须自行推出。

+0

谢谢 - 非常有用! :) – Andy0708