Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用前置处理器更改变量类型';s#ifdef_C++_C Preprocessor - Fatal编程技术网

C++ 使用前置处理器更改变量类型';s#ifdef

C++ 使用前置处理器更改变量类型';s#ifdef,c++,c-preprocessor,C++,C Preprocessor,我有两个应用程序“服务器”和“客户端”,它们依赖于许多相同的代码。 他们需要以不同的方式与控制台交互。我不想编写一个处理这两种情况的类,而是想在这两种不同的情况下包含两个不同的类。现在,在Globals.h和Globals.cpp中,我执行以下操作: Globals.h: #ifdef SERVER extern ConsoleUI ui; #else extern Logger ui; #endif Globals.cpp: #include "Globals.h" #ifdef SERVE

我有两个应用程序“服务器”和“客户端”,它们依赖于许多相同的代码。 他们需要以不同的方式与控制台交互。我不想编写一个处理这两种情况的类,而是想在这两种不同的情况下包含两个不同的类。现在,在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
然而,他们最终都创建了一个日志用户界面而不是控制台用户界面。 我之所以知道这一点,是因为服务器试图调用ConsoleUI和segfaults中存在的函数,因为出于某种原因,他的“ui”属于“Logger”类型

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


希望以前没有人问过这个问题,我搜索的所有内容都没有给我任何有用的点击率。

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

#include "Globals.h"
#ifdef SERVER
ConsoleUI ui;
#else
Logger ui;
#endif
实际上会转到
ifdef服务器
分支,这可能不是您想要的

为了按照您希望的方式进行条件编译,您需要使用命令行中的
#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
方法无法获得的。

您拥有的代码可能失败的原因是,如果您执行类似
#define SERVER
的操作,将创建
服务器
符号。如果您在其他地方也有
#define CLIENT
,则如下所示:

#include "Globals.h"
#ifdef SERVER
ConsoleUI ui;
#else
Logger ui;
#endif
实际上会转到
ifdef服务器
分支,这可能不是您想要的

为了按照您希望的方式进行条件编译,您需要使用命令行中的
#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
方法无法获得的。

您拥有的代码可能失败的原因是,如果您执行类似
#define SERVER
的操作,将创建
服务器
符号。如果您在其他地方也有
#define CLIENT
,则如下所示:

#include "Globals.h"
#ifdef SERVER
ConsoleUI ui;
#else
Logger ui;
#endif
实际上会转到
ifdef服务器
分支,这可能不是您想要的

为了按照您希望的方式进行条件编译,您需要使用命令行中的
#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
方法无法获得的。

您拥有的代码可能失败的原因是,如果您执行类似
#define SERVER
的操作,将创建
服务器
符号。如果您在其他地方也有
#define CLIENT
,则如下所示:

#include "Globals.h"
#ifdef SERVER
ConsoleUI ui;
#else
Logger ui;
#endif
实际上会转到
ifdef服务器
分支,这可能不是您想要的

为了按照您希望的方式进行条件编译,您需要使用命令行中的
#define
为服务器编译一次,为客户端编译一次。执行此操作的标志通常是
-D

因此,使用
#ifdef
方法编译