Как объединить один и тот же метод разных классов, которые используют закрытые члены - PullRequest
3 голосов
/ 13 декабря 2011

Я только что зарегистрировался здесь, поэтому прежде всего, спасибо за чтение!

Я занимаюсь разработкой приложения с использованием Qt, но мне нужно несколько советов относительно совместного использования членов класса.Я работаю с некоторыми коллекциями (QHash) специфичных для проекта структур, и я создал полиморфный класс для управления этими коллекциями.Производный класс также управляет некоторыми компонентами пользовательского интерфейса (совместно используемыми указателями или ссылками), поэтому он может автоматически представлять эти структуры в пользовательском интерфейсе. Это что-то вроде этого:

Основной класс

class ArmyEditor : public QMainWindow
{
//.... some specific functions ...

private:
    Ui::ArmyEditor *ui;

    // Specific structs
    QHash<QString, GameCategory> categories;
    QHash<QString, Column> columns;
    QHash<QString, GameProperty> properties;
    QHash<QString, UnitOption> commonOptions;
    QHash<QString, UnitOption> inheritedOptions;
    QHash<QString, GameItem> items;
    QHash<QString, GameItem> inheritedItems;
    QHash<QString, GlobalText> globalTexts;
    QHash<QString, GlobalText> inheritedGlobalTexts;
    QHash<QString, Unit> units;
};

Baseкласс для управления коллекциями ..

class StructManager : public QObject {
    Q_OBJECT
public:

    explicit StructManager(QWidget* parent = 0);

    // ...Functions that perform actions in shared components...

protected:
    QWidget *parent;
    QHash<QString, GameCategory> *categories;
    QHash<QString, Column> *columns;
    QHash<QString, GameProperty> *properties;
    QHash<QString, UnitOption> *commonOptions;
    QHash<QString, GameItem> *commonItems;
    QHash<QString, GlobalText> *globalTexts;
    QHash<QString, Unit> *units;
};

Производный класс для управления пользовательским интерфейсом и т. д.

class StructEditor : public StructManager
{
    Q_OBJECT
public:

    StructEditor(QWidget* parent = 0);

    // ...Overriden functions to automatically represent structs in the shared members..

protected:
    QTreeWidget *catList;
    QListWidget *colList;
    QTreeWidget *propList;
    QTreeWidget *optList;
    QListWidget *optActionList;
    QTreeWidget *itemList;
    QListWidget *itemActionList;
    QTableWidget *globalTextsGrid;
    QTreeWidget *unitTree;
    QComboBox *optCategory;
    QComboBox *itemCategory;
    QComboBox *unitCategory;
    QComboBox *optAmountColumn;
    QComboBox *optSetColumn;
};

И я разделяю некоторые члены пользовательского интерфейса в конструкторе класса MainWindow ..

ArmyEditor::ArmyEditor(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::ArmyEditor)
{
    ui->setupUi(this);

    // Setup Army Struct Manager

    armyManager = new StructEditor(this);

    armyManager->setCatList(ui->catList);
    armyManager->setOptList(ui->optList);
    armyManager->setOptActionList(ui->optActionList);
    armyManager->setItemList(ui->itemList);
    armyManager->setItemActionList(ui->itemActionList);
    armyManager->setGlobalTextsGrid(ui->globalTextsGrid);
    armyManager->setUnitTree(ui->unitTree);
    armyManager->setOptCategory(ui->optCategory);
    armyManager->setItemCategory(ui->itemCategory);
    armyManager->setUnitCategory(ui->unitCategory);
    armyManager->setOptAmountColumn(ui->optAmountColumn);
    armyManager->setOptSetColumn(ui->optSetColumn);
    armyManager->setCategories(&categories);
    armyManager->setOptions(&commonOptions);
    armyManager->setItems(&items);
    armyManager->setGlobalTexts(&globalTexts);

    //.. some other code ..
};

Я вызываю функции из класса StructEditor, когда мне нужно добавить новую категорию или что-то в этом роде. Мой проект состоит из трех приложений, те из которых используют почти одинаковые методы для управления этими структурами, поэтому ярешил использовать класс с методами для добавления, обновления, удаления и представления структур в пользовательском интерфейсе, совместно использующих некоторые указатели-члены с классом MainWindow.Но теперь я думаю, что это немного грязно, и я не должен делиться этими членами, потому что MainWindow теряет контроль над ними.Я думал, что смогу создать коллекции своих структур в классе Base и создать метод, чтобы я мог (безопасно) читать члены этих коллекций в классе MainWindow, но моя проблема с членами пользовательского интерфейса.Я мог бы использовать сигналы и управлять этими членами непосредственно в классе MainWindow, но тогда мне пришлось бы дублировать большую часть кода, и это усложнило бы (немного) изменения кода, что является основной причиной, по которой я решил объединить эти методы вclass.

Итак, мой вопрос таков: есть ли способ «объединить» эти методы без необходимости совместного использования членов или использования глобальных переменных (потому что это будет иметь тот же эффект)?Я хотел бы иметь эти методы в отдельном файле.

Спасибо и привет!

1 Ответ

0 голосов
/ 20 декабря 2011

Вам следует взглянуть на предоставленное вами наследство и местонахождение ваших данных.

Как указывал AJG85, вы должны отделить ваши данные от ваших манипуляторов и просмотреть их, например:

class StructManager {
private:
    typedef QHash<QString, GameCategory> CategoryT;
    CategoryT categories;
    ....
public:
    CategoryT& getCategories() { return categories; }
};

class StructEditor : public QObject
{
Q_OBJECT
protected:
    StructManager sm;
...
};

class ArmyEditor : public StructEditor
{
public:
    <manipulation methods>
};

class ArmyWindow : public MainWindow
{
private:
    ArmyEditor ae;
....
};

Как только вы ознакомитесь с этой структурой, вы обнаружите, что все события из пользовательского интерфейса могут передаваться в ваши редакторы, которые манипулируют данными и отображают поля, которые их читают.

Таким образом, у вас нет разделения данных между объектами и нет дублирования кода. Если вы хотите быть по-настоящему модным, сделайте следующее:

class BaseEditor
{
protected:
    void ManipulateCategories() = 0;
};

class StructEditor : public QObject, public BaseEditor
{
   ....
};

class ArmyEditor : public QObject, public BaseEditor
{
 ....
};

Я уверен, что вы можете выяснить реализации для отдельных классов редактора.

...