如何在多平台qt代码中避免特定的#ifdef?
How to avoid specific #ifdef in multi - platform qt code?
我有一个 QT 输入侦听器 class,它在 运行 QCoreApplication
中发出 stdin
输入信号。我想在 windows 和 linux.
上都使用它
我目前的做法是在header和cpp中使用#ifdef Q_OS_WIN
来执行platform-specific代码。据我所知,#ifdef
被认为是有害的,应该避免,我想以一种我有一个 header 文件 inputlistener.h
的方式重构它,让构建系统在一个具体的 windows/inputlistener.cpp
或 linux/inputlistener.cpp
,可能还有一个额外的 inputlistener_global.cpp
来保存代码,这不是平台特定的。
但是,我找不到解决办法,如何让 header 中的 #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);
}
}
您可以创建 WinEventListener
和 UnixEventListener
(或其他),每个都使用它自己的实现(而不是尝试通过 ifdefs 将其放入一个),每个都实现通用的 Listener
接口(并驻留在单独的文件中)。
然后,有一个 return 监听器适合 OS 的工厂函数。他们只有一个地方可能需要 ifdefs。
但总的来说,ifdef
做一些事情可能是最好的或唯一的行动方案(例如,当你已经抽象了一些东西时)。条件编译是预处理器的少数 valid/justified 用法之一(这就是它的用途)。
此外,在您的特定情况下,请确保 Qt 库中还没有合适的 code/class。对于大多数常见的东西,可能已经存在抽象(或推荐的方法)。
您可以为 windows
和 unix
创建单独的 EventListener.cpp
文件,并将这些文件放入子目录中,例如 (win
、linux
)。您可以向 makefile 或 projectfile 添加一个基于当前平台的实现文件。编译器将只为当前平台编译一个文件。
使用此方法可以完全避免 ifdef
ing。
如果定义不同你可以使用pImpl
成语来分隔class的实现细节:https://cpppatterns.com/patterns/pimpl.html
我有一个 QT 输入侦听器 class,它在 运行 QCoreApplication
中发出 stdin
输入信号。我想在 windows 和 linux.
我目前的做法是在header和cpp中使用#ifdef Q_OS_WIN
来执行platform-specific代码。据我所知,#ifdef
被认为是有害的,应该避免,我想以一种我有一个 header 文件 inputlistener.h
的方式重构它,让构建系统在一个具体的 windows/inputlistener.cpp
或 linux/inputlistener.cpp
,可能还有一个额外的 inputlistener_global.cpp
来保存代码,这不是平台特定的。
但是,我找不到解决办法,如何让 header 中的 #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);
}
}
您可以创建 WinEventListener
和 UnixEventListener
(或其他),每个都使用它自己的实现(而不是尝试通过 ifdefs 将其放入一个),每个都实现通用的 Listener
接口(并驻留在单独的文件中)。
然后,有一个 return 监听器适合 OS 的工厂函数。他们只有一个地方可能需要 ifdefs。
但总的来说,ifdef
做一些事情可能是最好的或唯一的行动方案(例如,当你已经抽象了一些东西时)。条件编译是预处理器的少数 valid/justified 用法之一(这就是它的用途)。
此外,在您的特定情况下,请确保 Qt 库中还没有合适的 code/class。对于大多数常见的东西,可能已经存在抽象(或推荐的方法)。
您可以为 windows
和 unix
创建单独的 EventListener.cpp
文件,并将这些文件放入子目录中,例如 (win
、linux
)。您可以向 makefile 或 projectfile 添加一个基于当前平台的实现文件。编译器将只为当前平台编译一个文件。
使用此方法可以完全避免 ifdef
ing。
如果定义不同你可以使用pImpl
成语来分隔class的实现细节:https://cpppatterns.com/patterns/pimpl.html