我有两个应用程序'服务器'和'客户端',它们依赖于许多相同的代码。他们需要以不同的方式与主机互动。我想在两种不同的情况下包含两个不同的类,而不是编写一个类来处理这两种情况。现在,在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
方法所没有的类型安全
问题可能是您没有一致地为每个人定义SERVER
或CLIENT
。将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'。