Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.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++ 如何避免在多平台qt代码中使用特定的#ifdef?_C++_Qt_Cross Platform_Multiplatform - Fatal编程技术网

C++ 如何避免在多平台qt代码中使用特定的#ifdef?

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之间进行选择,可能需要一个额

我有一个QT input listener类,它在运行的
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:我在答案中加入了这个扩展。