![](/img/trans.png)
[英]Using #ifdef or #if defined() to find where a variable is (not) defined
[英]Changing type of variable using prepocessor's #ifdef
我有两个依赖于许多相同代码的应用程序“服务器”和“客户端”。 他们需要与控制台交互的方式有所不同。 我不想编写处理这两种情况的类,而是想在两种不同的情况下包括两种不同的类。 现在,在Globals.h和Globals.cpp中,我这样做:
Globals.h:
#ifdef SERVER
extern ConsoleUI ui;
#else
extern Logger ui;
#endif
Globals.cpp:
#include "Globals.h"
#ifdef SERVER
ConsoleUI ui;
#else
Logger ui;
#endif
(我在标头中也包含了防护,但在这里将它们保留了下来)。
在服务器的主文件中,我定义:
#define SERVER
在客户端的主文件中,我使用:
#define CLIENT
但是,他们两个最终都创建了Logger ui而不是ConsoleUI ui。 我知道这是因为服务器尝试调用ConsoleUI和segfaults中存在的函数,因为由于某种原因,他的“ ui”属于“ Logger”类型。
我确实意识到,更干净的方法可能是将Globals分离为GlobalsClient.h / .cpp和GlobalsServer.h / .cpp,但是我想了解为什么上面的代码不起作用。
希望以前没有问过这个问题,我搜索的所有内容都没有给我带来任何帮助。
您拥有的代码很可能失败的原因是,如果您执行诸如#define SERVER
,它将创建SERVER
符号。 如果您在其他地方也有#define CLIENT
则请执行以下操作:
#include "Globals.h"
#ifdef SERVER
ConsoleUI ui;
#else
Logger ui;
#endif
实际上会ifdef SERVER
可能不是您想要的ifdef SERVER
分支。
为了按照您希望的方式进行条件编译,您需要使用#define
从命令行为服务器编译一次,为客户端编译一次。 执行此操作的标志通常是-D
。
因此,使用#ifdef
方法为服务器编译时,您将执行以下操作
g++ -DSERVER -o server_output_name
对于客户:
g++ -DCLIENT -o client_output_name
但是重要的是要认识到,总的来说,有更好的方法可以用c ++来实现所需的功能。 具体来说,您想让语言为您做类型检查,而不是依赖相对来说“不安全”的预处理器。 如果有很多通用代码,那么如何制作一个包含该代码的基类并具有两个实现非通用代码的派生类呢?
就像是:
class UIBase{
protected:
//all the common code
};
class UIServer : public UIBase{
//server specific code and implementation
};
class UIClient : public UIBase{
//client specific code and implementation
};
这样,您可以根据对象的类型创建对象,并使用c ++语言确保根据上下文调用正确的代码。 您可以通过#define
方法获得某种类型的安全性。
问题可能是您没有对每个人都正确地定义SERVER
或CLIENT
。 将Globals.h更改为:
#ifdef SERVER
#ifdef CLIENT
#error "Both CLIENT and SERVER defined!"
#endif
#define ui ServerUI
extern ConsoleUI ui;
#elif defined(CLIENT)
#define ui ClientUI
extern Logger ui;
#else
#error "Neither CLIENT nor SERVER defined!"
#endif
现在,如果缺少SERVER和/或CLIENT的设置或其他损坏的设置,您将得到编译器或链接器错误,而不是运行时崩溃。
确保在主cpp中包含“ Globals.h”之前放入“ #define SERVER”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.