0

我有两节课

class Car
{
// class Car related methods
public:
setDriversName(QString);
private:
String driversName_;    // This information comes from class DriversName

//Must get the drivers name info, when a particular event in this object occurs;
}

class DriversName
{
//class DriversName related methods
String getDriversName();
private:
String driversName_;
}

所以,现在我想在两个类之间进行通信,更具体地说,我希望类在 Car Object 中发生特定事件时从类Car中获取驱动程序的名称。DriversName

到目前为止,我有这两种方法,

C++ Message passing:

class Car
{
// class Car related methods
public:
setDriversNameObject(DriversName& );
setDriversName()
{
   driversName_ =  DriversName.getDriversName();
}

private:
DriversName driversName_;    // So after setting the Driverclass object, i can directly 
//access the driver's name, whenever the event occurs
String driversName_;
}

class DriversName
{
//class DriversName related methods
String getDriversName();

private:
DriversName driversName_;
}

或者

Qt

In mainWindow class:

connect(carObject,eventHasOccured(),this,updateDriversName());


void MainWindow::updateDriversName()
{
    carObject->setDriversName(driversNameObject.getDriversName);
}

Class Car
{
    Q_OBJECT
    signals:
    emit eventHasOccured();

    public:
    setDriversNameObject(DriversName& );

    private:
    DriversName driversName_;              
}

Class DriversName
{
    Q_OBJECT

    String getDriversName();

    private:
    DriversName driversName_;    
}

这两种解决方案肯定会奏效。以下是我的问题:

1)上述方法在OO原则方面是否有任何缺陷。

2) 处理这种情况的最标准方法是什么?

3)有没有其他更好的方法来处理给定的情况。

谢谢。

4

2 回答 2

1

1)上述方法在OO原则方面是否有任何缺陷。

第一种方法将Car方法与DriversName类紧密结合。

第二个将您的应用程序与 Qt 耦合。无论如何,如果您在整个应用程序中都使用它,这不是什么大问题,但应该考虑一下。此外,它将业务逻辑代码移动到主窗口类中,这可能不是一个好主意。

2) 处理这种情况的最标准方法是什么?

没有“一种确定的方法”可以做到这一点。只是更好和更差的。

3)有没有其他更好的方法来处理给定的情况。

对于“纯 C++”方法,您可以引入一个抽象接口来侦听驱动程序名称更改(或者甚至更通用地用于侦听通用名称更改)。我在这里指的基本上是实现观察者模式。一个简化的实现可能如下所示:

class NameChangeListener
{
public:
    virtual void onNameChange(std::string const & newName) =0;
};

// This assumes change is initiated in DriversName class - not sure if this is correct
// Your code doesn't show the actual triggering of the change
class DriversName
{
public:
// ... other stuff
    setNameChangeListener(NameChangeListener* ncl)
    {
        changeListener = ncl;
    }
    void setName(std::string const & newName)
    {
        // ... other stuff
        if (changeListener)
            changeListener->onNameChange(newName);
    }
private:
    // ..
    NameChangeListener* changeListener;
};

class Car: public NameChangeListener
{
public:
// ... other stuff
    void onNameChange(std::string const & newName) {
        driversName = newName;
    }
};

// somewhere outside:
Car c1;
DriversName n;
n.setNameChangeListener(c1);

对于 Qt 方法,最好引入一个封装此类关系的附加“控制器”类,而不是直接在主窗口中进行。

于 2013-10-15T12:33:57.363 回答
1

除了 nyarlathotep 的回答,还有更多细节:

1)如果您确实需要在特定事件发生时进行更新,那么第一个解决方案是不够的,因为它不处理事件;应该明确调用Car's setDriversName()。通常,您确实需要一个信号/插槽或回调机制,例如第二种解决方案。在这种情况下,我认为您宁愿需要类似的东西

connect(driversNameObject,nameChanged(string),carObject,setDriversName(string));

应用程序/主窗口都不carObject需要知道任何关于driversNameObject. setDriversName除此之外,我认为您的第二个解决方案中存在许多小错误(例如,Car.

2) 和 3) 如果我还没有从事 QT 项目,我个人会避免使用 QT 的信号/槽机制。这种机制完全绕过了 C++ 语言,需要通过自己的工具对源文件进行预处理。一个后果是,在编译器有任何检查机会之前,所有内容(如方法名称)都被作为字符串处理。另一个是您需要一种特定的方式来构建您的项目,这种方式比必要的方式复杂得多,并且会使其他库的使用更加困难。

至于更多“纯 C++”解决方案,我敢打赌,例如Boost.Signals会完成这项工作,但同样可能会带来太多您不需要的复杂性。

我开发了一个纯 C++ 抽象接口,它基于delegates完全模仿 QT 信号/插槽的行为,但这涉及内部的低级内容,例如强制转换为void*. 当然,另一种选择是std::function在内部使用。它在处理所有函数调用语言特性方面仍然不是完全通用的,例如派生类中的方法、重载、虚拟方法、默认参数等等(但 Boost.Signals 也不是)。我打算在完成之前使用可变参数模板在 C++11 中重新实现它。

同样,我(仍然)不知道一个完美的或事实上的标准解决方案。

于 2013-10-15T13:08:24.370 回答