Qt C++ 根据组合框中的选择创建对象

Qt C++ creating an Object according to choice in combobox

由于本人对面向对象代码的设计经验不是很丰富,所以有以下问题:

我有一个组合框 cb_GRAN,其中包含 21 个条目,代表 21 个几何图形。根据 cb_GRAN 中的选择,我想开始对我的几何体表面进行不同的计算(实际上还有更多:更复杂的计算,on/of-switching LineEdits 等.但为了简单起见,我们只讨论曲面的计算。)

为了解决这个问题,我创建了一个 class Geometry 和 21 类 (Geo_1, Geo_2,...Geo_21) 继承自 Geometry。我还有一个虚方法

virtual void calculateSurface();

为了定义classGeo_x是创建和计算表面,我想到了以下想法:

Geometry *GEO;
QVector < Geometry*> qvec_GEO      

qvec_GEO << new Geo_1()<< new Geo_2()<< new Geo_3()<<......  << new Geo_21() ;

GEO =  qvec_GEO[ui->cb_GRAN->currentIndex()];
GEO->calculateSurface();

问题一: 您的解决方案可能会运行良好(仅基于您提供的信息)。

问题二: 你完全正确,如果你打算只使用其中的 1 个或 2 个,则创建所有 21 个 class 的实例可能是一种矫枉过正。

您必须找到一种解决方案来仅实例化所需的 class。 Qt 提供了一个元对象系统,您可以为此使用。基本上,您将不得不使用 QMetaType class.

首先,您必须在元对象系统中注册 "Geo_N" classes。您有很多解决方案可以做到这一点,但在您的情况下最好的方法可能是在 class 定义之后使用声明性宏:

class Geo_1 {
    Q_OBJECT
    void Geo_1();
};
Q_DECLARE_METATYPE(Geo_1);

请注意,如果您想在元对象注册表中注册 class,则必须使用 Q_OBJECT 宏。

然后,您将能够动态实例化任何已注册的类型:

// The index of selected class (between 1 and 21)
int geoIndex = ui->cb_GRAN->currentIndex();

// Re-build the corresponding class name
QString typeName = "Geo_" + QString::number(geoIndex);

// Retrieve the type ID corresponding to the type name
int typeId = QMetaType::type(typeName.toStdString().c_str());

// Instantiate the corresponding class
Geometry* geo = (Geometry*) QMetaType::construct(typeId);

我的方法是为您的几何图形定义一个工厂class

class GeoFactory{
  enum GeometryType { GEO_1, GEO_2, ... );
  std::uique_ptr<Geometry> create( GeometryType type );
}

然后将 GeometryType 添加到数据角色中的组合框项目。在当前更改的事件中,您只需从当前索引中检索 GeometryType 并从工厂请求相应的对象。

就我个人而言,我总是尽量让 Qt 远离实际的业务逻辑,我只使用 for UI。