C++ 如何避免在多平台qt代码中使用特定的#ifdef?
我有一个QT input listener类,它在运行的C++ 如何避免在多平台qt代码中使用特定的#ifdef?,c++,qt,cross-platform,multiplatform,C++,Qt,Cross Platform,Multiplatform,我有一个QT input listener类,它在运行的QCoreApplication中发出stdin输入信号。我想在windows和linux上都使用它 我目前的方法是在header和cpp中使用#ifdef Q_OS_WIN来执行特定于平台的代码。正如我所知,ifdef被认为是有害的,应该避免,我想用一个头文件inputlistener.h重构它,让构建系统在特定的windows/inputlistener.cpp或linux/inputlistener.cpp之间进行选择,可能需要一个额
QCoreApplication
中发出stdin
输入信号。我想在windows和linux上都使用它
我目前的方法是在header和cpp中使用#ifdef Q_OS_WIN
来执行特定于平台的代码。正如我所知,ifdef被认为是有害的,应该避免,我想用一个头文件inputlistener.h
重构它,让构建系统在特定的windows/inputlistener.cpp
或linux/inputlistener.cpp
之间进行选择,可能需要一个额外的inputlistener\u global.cpp
来保存代码,它不是特定于平台的
但是,我找不到一个解决方案,如何将标题中的#ifdef
去掉
我怎样才能做到这一点
以下是我目前的做法:
#inputlistener.h
#ifndef INPUTLISTENER_H
#define INPUTLISTENER_H
#include <QtCore>
class inputlistener : public QObject {
Q_OBJECT
private:
#ifdef Q_OS_WIN
QWinEventNotifier* m_notifier;
#else
QSocketNotifier* m_notifier;
#endif
signals:
void inputeventhappened(int keycode);
private slots:
void readyRead();
public:
inputlistener();
};
#endif // INPUTLISTENER_H
#inputlistener.cpp
#include "inputlistener.h"
#include "curses.h"
#ifdef Q_OS_WIN
#include <windows.h>
#endif
inputlistener::inputlistener()
{
#ifdef Q_OS_WIN
m_notifier = new QWinEventNotifier(GetStdHandle(STD_INPUT_HANDLE));
connect(m_notifier, &QWinEventNotifier::activated
#else
m_notifier = new QSocketNotifier(0, QSocketNotifier::Read, this);
connect(m_notifier, &QSocketNotifier::activated
#endif
,
this, &inputlistener::readyRead);
readyRead(); // data might be already available without notification
}
void inputlistener::readyRead()
{
// It's OK to call this with no data available to be read.
int c;
while ((c = getch()) != ERR) {
emit inputeventhappened(c);
}
}
#inputlistener.h
#ifndef输入侦听器\u H
#定义输入侦听器
#包括
类inputlistener:公共QObject{
Q_对象
私人:
#如果你赢了
QWinEventNotifier*m_通知程序;
#否则
QSocketNotifier*m_通知程序;
#恩迪夫
信号:
无效InputEventOccessed(int-keycode);
专用插槽:
void readyRead();
公众:
inputlistener();
};
#endif//INPUTLISTENER\u H
#inputlistener.cpp
#包括“inputlistener.h”
#包括“curses.h”
#如果你赢了
#包括
#恩迪夫
inputlistener::inputlistener()
{
#如果你赢了
m_notifier=新的QWinEventNotifier(GetStdHandle(STD_输入_句柄));
连接(m_通知程序和QWinEventNotifier::已激活
#否则
m_notifier=新的QSocketNotifier(0,QSocketNotifier::Read,this);
连接(m_通知程序和QSocketNotifier::已激活
#恩迪夫
,
这是(输入侦听器::readyRead);
readyRead();//数据可能已在不通知的情况下可用
}
void inputlistener::readyRead()
{
//在没有可读取的数据的情况下调用它是可以的。
INTC;
而((c=getch())!=ERR){
发出InputEventOccessed(c);
}
}
您可以创建WinEventListener
和UnixEventListener
(或其他内容),每个都使用自己的实现(而不是试图通过ifdef将其装入一个),每个实现通用侦听器
接口(并驻留在单独的文件中)
然后,使用一个工厂函数返回适合操作系统的监听器。它们将只有一个地方可能需要ifdef
但一般来说,ifdef
ing某物可能是最好的或唯一的操作过程(例如,当您已经抽象某物时)。条件编译是预处理器为数不多的有效/合理用法之一(这就是它的用途)
另外,在您的特定情况下,确保Qt库中没有合适的代码/类。对于大多数常见的东西,可能已经存在抽象(或推荐的方法).您可以为
windows
和unix
创建单独的EventListener.cpp
文件,并将这些文件放入子目录,如(win
,linux
)。您可以在makefile或projectfile中添加一个基于当前平台的实现文件。编译器将只为当前平台编译一个文件
使用此方法可以完全避免ifdef
ing
如果定义不同,您可以使用
pImpl
习惯用法来分隔类的实现细节:不正确的说法是“#ifdef
有害”.这是一个品味的问题,取决于特定的应用程序和情况。我不会担心这一点,除非它会导致真正的问题。你会为了一些教条而放大你的代码。那只是移动“ifdef”我知道这是一种有效的方法。但我担心的是标题,因为定义也不同,而不仅仅是实现。如果定义不同,你可以使用pImpl
idiom来分隔类的实现细节:@devjb:我在答案中加入了这个扩展。