Pergunta

Eu tenho um pedaço deselegante de código C++ Qt onde main cria um item gráfico (o pai) que cria vários itens gráficos filhos.O filho e o pai devem chamar os métodos um do outro, ou seja,os pais precisam dizer aos filhos para fazerem algumas coisas (mover-se, mudar de cor, etc.), e os filhos sinalizarão aos pais para fazerem coisas com os outros filhos.Fazer com que ambos chamem os métodos um do outro está levando a um código circular feio e está se tornando frustrante evitar erros C2027.Faria algum sentido usar um sistema de sinal/slot personalizado como método de comunicação entre a criança e os pais?Ou devo continuar com meu design atual e apenas tentar resolver esses tipos de bugs?

Por exemplo, este código (meu design atual) gera C2027:

Janela principal:

#include "mainwindow.h"
#include "ui_mainwindow.h"

vector<Foo*> FooArray;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    scene = new QGraphicsScene(this);
    ui->graphicsView->setScene(scene);

    int viewwidth = ui->graphicsView->width();

    ...

    FooArray.push_back(new Foo(5, viewwidth, scene));
    FooArray[0]->loadBars();
}

Foo:

#include "Foo.h"  //includes bar.h


vector<int> ActiveList;
vector<Bar*> BarArray;

Foo::Foo(int id, int w, QGraphicsScene* scene)
{
    this->id = id;
    this->width = w;
    this->scene = scene;
}

...

void Foo::loadBars()
{
    ...
    BarArray.resize(nitems);
    BarArray[k] = new Bar(id, k, this);
    BarArray[k]->setPos(...);
    scene->addItem(BarArray[k]);
    ...
}

void Foo::doSomething()
{
    ...
}

Bar:

#include "Bar.h"  //forward declares Foo; isn't executed until Foo exists. 

Bar::Bar(int setid, int num, Foo* foo)
{
    this->s = setid;
    this->n = num;
    this->owner = foo;
}

...

void Bar::someFunction()
{   
    ...
    owner->doSomething();
    ...
}
Foi útil?

Solução

Sim, é exatamente para isso que servem os sinais e slots.

Agora você tem Bar::someFunction() que chama Foo::doSomething()

O que você pode fazer é:

  1. Declarar doSomething() como um slot
  2. Faça com que Bar emita um sinal somethingHappened()
  3. Ao criar os filhos, conecte seus somethingHappened() sinal para os pais doSomething() slot

Este é um exemplo de injeção de dependência e permite trocar a classe pai por outra coisa no futuro sem precisar alterar Bar de forma alguma.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top