我有一个类定义,我想添加一个成员变量,该变量可以是 2 个不同类之一,具体取决于运行此代码的操作系统。
是否有办法在 C++ 中执行此操作,以便我可以在初始化
operating_system
时根据某些参数或变量为 MyOperatingSystem
成员变量初始化不同的类?
#include <iostream>
#include "Win.h"
#include "Lin.h"
using namespace std;
typedef int os_type;
enum {Win, Lin};
class MyOperatingSystem {
public:
MyOperatingSystem(int ver, string n, os_type os);
private:
int version;
string name;
// operating_system // want this to be either (Windows win | Linux lin)
};
// constructor
MyOperatingSystem::MyOperatingSystem(int ver, string n, os_type os){
version = ver;
name = n;
if (os == Win){
// operating system = Windows(int i);
}
else{
// operating system = Linux(int i)
}
}
Win.h和Lin.h如下
Win.h:
#include <windows.h>
class Windows{
public:
Windows(int i){
integer = i;
mystring = "WinString";
}
private:
int integer;
LPCWSTR mystring;
};
林.h:
#include <termios.h>
class Linux{
public:
Linux(int i){
integer = i;
mystring = "LinString";
}
private:
int integer;
cc_t* mystring;
};
我建议做出编译时决定。
示例:
#pragma once // MyOperatingSystem.h
class IOperatingSystem {
public:
virtual ~IOperatingSystem() = default;
// misc operations:
virtual foo() = 0;
};
#ifdef _WIN32
#include "internal/Win.h" // in here MyOperatingSystem implements IOperatingSystem
#else
#include "internal/Lin.h" // in here MyOperatingSystem implements IOperatingSystem
#endif
您不一定需要
virtual
,但在设计时它会有所帮助,以确保两个实现都遵循相同的接口。
最明显的解决方案是拥有一个具有公共接口的
OperatingSystem
基类,并从中派生 Win
和 Linux
。
操作系统是编译时的事情,因此您可以使用模板参数
template <ostype os> class MyOperatingSystem ...
然后您可以使用
if constexpr
检查您拥有哪些操作系统并在类中包含不同的代码。 Windows
和 Linux
类可能应该有一个共同的基类,然后大多数差异将通过虚拟方法来解决。所以 if constexpr (os == Win) ...
应该是例外。
另一种方法是依赖项插入:
MyOperatingSystem(int ver, string n, Os & os);
其中
Os
是 Windows
和 Linux
的公共基类。
或者再说一遍,因为这是编译时的事情:
template <typename Os> class MyOperatingSystem : public Os { ... }
template <typename Os> class MyOperatingSystem { ... Os os; }
在这种情况下,您甚至不需要公共基类(但它有助于确保公共接口)。
Windows
和 Linux
都只需遵循一个通用接口,例如定义 os_type
。如果 Os::os_type
是 constexpr,您可以再次使用 if constexpr
。但我认为 Os 类的重点是封装所有操作系统特定的代码,因此如果使用的话,这种情况应该很少见。
请注意,使用
Os
模板方式,MyOperatingSystem
类是(或具有)具体的 Windows
或 Linux
类。因此,所有虚拟函数调用都被具体调用所取代。所以没有开销。早期的情况有一个指向基类的指针或引用,并且需要进行虚拟方法调用。
std::variant<Windows, Linux> operating_system;
std::variant
是一个求和类型——它是类型列表中的类型之一。
作为一个副作用,它带有它本身的类型——所以
os_type
变量存储在它旁边是多余的。