Qt: Сигналы и слоты против C ++: передача сообщений

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 получил имя драйвера из класса DriversName когда определенное событие встречается в Car Object.

Пока у меня есть два способа,

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 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) есть ли другой лучший метод для обработки данной ситуации.

Благодарю.

Теги:
qt
oop

2 ответа

1
Лучший ответ

1) Есть ли недостаток в вышеуказанных методах в отношении принципов OO.

Первый подход DriversName метод Car с классом DriversName.

Второй соединяет ваше приложение с Qt. Если вы все равно используете его во всем своем приложении, это не большая проблема, но его следует учитывать. Кроме того, он перемещает код бизнес-логики в класс mainwindow, что может и не быть такой хорошей идеей.

2) Каким образом можно справиться с этой ситуацией?

Для этого нет "одного окончательного способа". Просто лучше и хуже.

3) есть ли другой лучший метод для обработки данной ситуации.

Для "чистого C++" подхода вы можете ввести абстрактный интерфейс для прослушивания изменений имени драйвера (или, может быть, даже более общего для прослушивания общих изменений имен). То, что я имею в виду здесь, в основном реализует шаблон Observer. Например, упрощенная реализация может выглядеть следующим образом:

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 может быть полезно ввести дополнительный класс "Контроллер", инкапсулирующий такие отношения, вместо того, чтобы делать это непосредственно в главном окне.

  • 0
    Спасибо, но можете ли вы привести пример, демонстрирующий introducing an abstract interface for listening to driver name changes (or maybe even more generically for listening to generic name changes).
  • 0
    Действительно хорошее вступление в новый мир шаблонов наблюдателей ... Действительно хороший пример и ответ об исключениях в ссылке, размещенной о шаблонах наблюдателей ...
1

Еще несколько деталей на вершине nyarlathotep:

1) Если вам определенно необходимо, чтобы обновление происходило при возникновении определенного события, то первое решение недостаточно, потому что оно не обрабатывает события; нужно явно вызвать Car setDriversName(). Вам нужен сигнал/слот или механизм обратного вызова вообще, как и второе решение. В этом случае, я думаю, вам скорее понадобится что-то вроде

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

где ни приложение/главное окно, ни carObject должны знать ничего о driversNameObject. Кроме того, я думаю, что в вашем втором решении есть несколько небольших ошибок (например, в Car нет метода setDriversName.

2) и 3) я лично лично избегаю механизма QT signal/slot, если я еще не работаю в проекте QT. Этот механизм полностью обходит язык C++ и требует предварительной обработки исходного файла своими собственными инструментами. Одним из следствий является то, что все (например, имена методов) обрабатывается как строка, прежде чем компилятор имеет возможность проверить. Другое дело, что вам нужен конкретный способ создания вашего проекта, который намного сложнее, чем необходимо, и затруднит использование других библиотек.

Что касается более "чистых" решений C++, я уверен, например, Boost.Signals выполнили бы эту работу, но опять же, вероятно, это принесло бы слишком много сложностей, которые вам не нужны.

Я разработал абстрактный интерфейс C++, который точно имитирует поведение сигналов/слотов QT на основе делегатов, но это включает в себя низкоуровневые вещи внутри, такие как литье в void*. Альтернативой было бы, конечно, использовать std::function во внутренних элементах. Он по-прежнему не является полностью общим для обработки всех функций языка вызова функций, например методов в производных классах, перегрузки, виртуальных методов, аргументов по умолчанию и т.д. (Но ни один из них не является Boost.Signals). Я намерен повторно реализовать его в C++ 11, используя вариативные шаблоны, прежде чем завершать его.

Опять же, я (до сих пор) не знаю идеального или де-факто стандартного решения.

  • 0
    Спасибо за Ваш ответ....
  • 0
    Исправление: В Qt5 сигналы и слоты проверяются во время компиляции (нет макросов SIGNAL () и SLOT ())
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню