Pregunta

Tengo una porción poco elegante de código C++ Qt donde main crea un elemento gráfico (el padre) que crea un montón de elementos gráficos secundarios.El niño y el padre tienen que llamarse métodos entre sí, es decir.el padre necesita decirle a sus hijos que hagan algunas cosas (moverse, cambiar de color, etc.), y los niños le indicarán al padre que haga cosas a sus otros hijos.Hacer que ambos llamen a los métodos de los demás genera un código circular feo y resulta frustrante esquivar los errores C2027.¿Tendría algún sentido utilizar un sistema de señal/ranura personalizado como método de comunicación entre el niño y el padre?¿O debería mantener el rumbo con mi diseño actual e intentar resolver este tipo de errores?

Por ejemplo, este código (mi diseño actual) genera C2027:

Ventana 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();
    ...
}
¿Fue útil?

Solución

Sí, para eso precisamente están las señales y las tragamonedas.

Ahora mismo tienes Bar::someFunction() que llama Foo::doSomething()

Lo que puedes hacer en su lugar es:

  1. Declarar doSomething() como una ranura
  2. Haz que Bar emita una señal somethingHappened()
  3. Al crear a los niños, conecte sus somethingHappened() señal a los padres doSomething() ranura

Este es un ejemplo de inyección de dependencia y le permite cambiar la clase principal por otra cosa en el futuro sin tener que cambiar. Bar en absoluto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top