c++ - 打开对象的实际类型的正确方法是什么?

标签 c++ oop qt design-patterns sax

我正在编写一个 xml 解析器,我需要将对象添加到一个类中,并打开对象的实际类型。问题是,我想保留一个简单的接口(interface) addElement(BaseClass*) 然后正确放置对象。

void E_TableType::addElement(Element *e)
{
    QString label = e->getName();
    if (label == "state") {
        state = qobject_cast<E_TableEvent*>(e);
    }
    else if (label == "showPaytable") {
        showPaytable = qobject_cast<E_VisibleType*>(e);
    }
    else if (label == "sessionTip") {
        sessionTip = qobject_cast<E_SessionTip*>(e);
    }
    else if (label == "logoffmedia") {
        logoffMedia = qobject_cast<E_UrlType*>(e);
    }
    else {
        this->errorMessage(e);
    }
}

这是调用类,一个对象工厂。 myElement 是 E_TableType 的实例。

F_TableTypeFactory::F_TableTypeFactory()
{
    this->myElement = myTable = 0;
}

void F_TableTypeFactory::start(QString qname)
{
     this->myElement = myTable = new E_TableType(qname);
}

void F_TableTypeFactory::fill(const QString& string)
{
  // don't fill complex types.
}

void F_TableTypeFactory::addChild(Element* child)
{
    myTable->addElement(child);
}

Element* F_TableTypeFactory::finish()
{
    return myElement;
}

void F_TableTypeFactory::addAttributes(const QXmlAttributes &attribs) {
    QString tName = attribs.value(QString("id"));
    myTable->setTableName(tName);
}

最佳答案

你考虑过在这里使用多态吗?如果您的每个具体类都可以实现一个公共(public)接口(interface),那么所有这些代码都会消失,并且将来会变得简单且易于更改。例如:

class Camera {
public:
    virtual void Init() = 0;
    virtual void TakeSnapshot() = 0;
}

class KodakCamera : Camera {
public:
    void Init() { /* initialize a Kodak camera */ };
    void TakeSnapshot() { std::cout << "Kodak snapshot"; }
}

class SonyCamera : Camera {
public:
    void Init() { /* initialize a Sony camera */ };
    void TakeSnapshot() { std::cout << "Sony snapshot"; }
}

因此,假设我们有一个包含硬件设备的系统,在本例中为相机。每个设备需要不同的逻辑来拍照,但代码必须支持具有任何支持相机的系统,因此我们不希望 switch 语句散落在我们的代码中。所以,我们创建了一个抽象类Camera

每个具体类(即SonyCameraKodakCamera)的实现都将包含不同的头文件、链接到不同的库等,但它们都共享一个公共(public)接口(interface);我们只需决定预先创建哪一个。所以……

std::unique_ptr<Camera> InitCamera(CameraType type) {
    std::unique_ptr<Camera> ret;
    Camera *cam;
    switch(type) {
    case Kodak:
        cam = new KodakCamera();
        break;
    case Sony:
        cam = new SonyCamera();
        break;
    default:
        // throw an error, whatever
        return;
    }

    ret.reset(cam);
    ret->Init();
    return ret;
}

int main(...) {
    // get system camera type
    std::unique_ptr<Camera> cam = InitCamera(cameraType);
    // now we can call cam->TakeSnapshot 
    // and know that the correct version will be called.
}

现在我们有了一个实现Camera 的具体实例。我们可以调用 TakeSnapshot 而无需检查代码中任何地方的正确类型,因为这无关紧要;我们知道将调用正确硬件的正确版本。希望这对您有所帮助。

根据您的以下评论:

I've been trying to use polymorphism, but I think the elements differ too much. For example, E_SessionTip has an amount and status element where E_Url just has a url. I could unify this under a property system but then I lose all the nice typing entirely. If you know of a way this can work though, I'm open to suggestions.

我建议将编写 XML 数据的责任转移给共享公共(public)接口(interface)的类型。例如,而不是像这样:

void WriteXml(Entity *entity) {
   switch(/* type of entity */) {
      // get data from entity depending
      // on its type and format
   }

   // write data to XML
}

做这样的事情:

class SomeEntity : EntityBase {
public:
    void WriteToXml(XmlStream &stream) {
        // write xml to the data stream.
        // the entity knows how to do this,
        // you don't have to worry about what data
        // there is to be written from the outside
    }
private:
    // your internal data
}

void WriteXml(Entity *entity) {
    XmlStream str = GetStream();
    entity->WriteToXml(stream);
}

这对你有用吗?我以前做过这个,它对我有用。让我知道。

关于c++ - 打开对象的实际类型的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11297752/

相关文章:

c++ - 如何在 Qt 的 Mac 应用程序包中 bundle dylib?

c++ - 使用二叉搜索树重载运算符

c++ - 指向任意函数的 "general function signature"指针

javascript - Function.prototype.method 什么是原型(prototype)[名称]

c++ - 类中类 - 不允许不完整的类型

java - 设置聚合特征

c++ - 错误 : could not convert ‘((const MyClass*)this)->MyClass::myLabel’ from ‘QLabel* const’ to ‘QLabel’

c++ - 如何让 QLabel 扩展到全宽?

c++ - 将 "this"对象的 shared_ptr 获取到另一个函数 : giving run time exception

c++ - 有没有办法帮助编译器处理复杂的参数推导?