使用预处理器的 #ifdef 更改变量的类型

Changing type of variable using prepocessor's #ifdef

本文关键字:改变 变量 类型 #ifdef 预处理 处理器      更新时间:2023-10-16

我有两个应用程序'服务器'和'客户端',它们依赖于许多相同的代码。他们需要以不同的方式与主机互动。我想在两种不同的情况下包含两个不同的类,而不是编写一个类来处理这两种情况。现在,在global .h和global .cpp中,我这样做:

上面:

#ifdef SERVER
extern ConsoleUI ui;
#else
extern Logger ui;
#endif

Globals.cpp:

#include "Globals.h"
#ifdef SERVER
ConsoleUI ui;
#else
Logger ui;
#endif

(我在header中也有include守卫,但在这里没有提到)。

在Server的主文件中,我定义:

#define SERVER

,在客户端的主文件中,我使用:

#define CLIENT

然而,它们最终都创建了一个Logger ui而不是一个ConsoleUI ui。我知道这是因为服务器试图调用存在于ConsoleUI和segfaults中的函数,因为出于某种原因,他的"ui"类型为"Logger"。

我确实意识到一种更简洁的方法可能是将Globals拆分为globalclient .h/.cpp和GlobalsServer.h/.cpp,但我想了解为什么上面的代码不起作用。

希望以前没有人问过这个问题,我搜索的所有东西都没有给我任何有用的结果。

代码可能失败的原因是,如果您执行类似#define SERVER的操作,将创建SERVER符号。如果你在其他地方也有#define CLIENT,那么如下:

#include "Globals.h"
#ifdef SERVER
ConsoleUI ui;
#else
Logger ui;
#endif

实际上会进入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方法所没有的类型安全

问题可能是您没有一致地为每个人定义SERVERCLIENT。将global .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

现在,如果你有丢失或其他损坏的服务器和/或客户端设置,你会得到一个编译器或链接器错误,而不是运行时崩溃。

请确保在主cpp中包含' global .h'之前添加了'#define SERVER'。