Соединение множества классов вместе

0

Хм, я действительно не знаю, какой титул будет лучшим. Итак, я пытаюсь реализовать "логический конструктор схем" (а не домашнюю работу, для обучения). Я начал с простого примера: учитывая входной порт, выходной порт, 2 провода, источник питания и реле. Схема будет выглядеть так:

  • входной порт подключен к 1-му проводу
  • выходной порт iis подключен к 2-му проводу
  • другой конец второго провода подключен к мощности
  • 2 провода подключены посередине с помощью реле

Выглядит как:

->in------------------------>
                         |
        power-----------relay----------out->

Это просто отрицает входной бит. Я реализую его в C++, поэтому хочу создать хорошую иерархию классов. Как вы видите, входы могут быть подключены к проводам, выходам к проводам, проводам к реле и другим вариантам. Для этого у меня есть пустой port класса, и это базовый класс всех проводов, реле и т.д. Пример кода может выглядеть так:

struct port {
    //nothing
};

struct power : public port {
    bool poweron = true;
};

struct relay : public port {
    port* input;
    bool on; //will depend on input wire signal
};

struct wire : public port {
    port* input; //input end
    port* output; //output end
    std::vector<port*> outports; //output sockets for additional branching
    std::vector<port*> inports;  //input sockets for additional branching
};

struct bit_input : public port {
    port* output; //bit input can be vector too
};

struct bit_output : public port {
    port* input; //only one input bit to the bit output (lol)
};

int main(void)
{
    bit_input bin;
    bit_output bout;
    wire w0, w1;
    power p;
    relay r;

    ////////////////////////////////////////////////////////////////////////////////////////////////

    bin.output = &w0; //input wire connected to boolean input output:    ->bin------->
    bout.input = &w1;  //output wire connected to boolean output input:         ------->bout->

    w1.input = &p; //output wire input end is set to the power supply        power------->bout->
    w1.output = &bout; //output wire output end is set to the boolean output

    w0.input = &bin; //input wire input end is set to the boolean input output

    ////////////////////////////////////////////////////////////////////////////////////////////////

    w0.outports.push_back(&r); //one of input wire output port is set to the relay;     ->bin---|--->
                                                                                    //          relay
                                                                                    //     power--|---->bout->
    w1.inports.push_back(&r); //relay is connected to one of output wire inut ports too

    ////////////////////////////////////////////////////////////////////////////////////////////////

    r.input = &w0; //relay input bit is set to input wire

    return 0;
};

Это просто быстрый код, без интерфейса для выполнения соединений. Итак, есть (конечно, есть) лучшие способы сделать такую иерархию, с большим количеством ссылок на все вместе. Это был просто пример, потому что он все еще не обрабатывает сигналы, ветвление и так далее...

Основная проблема заключается в использовании указателей для соединения частей вместе, потому что для этого я должен отслеживать типы при указателях разыменования. Поэтому я мог бы использовать указатели void для этого... Я пытался использовать прямо указатели на эти структуры, но должен был создавать шаблоны, например, wire<power_supply, wire<whatever,whatever>> для подключения входного провода можно подключить к источнику питания, конец на другой провод. Но провод - это шаблон, поэтому, когда я хочу подключить до 1000 проводов, это не приводит к чему-то хорошему. Я не нашел хороших решений в случае более чем двух классов, на которые нужно ссылаться друг друга.

  • 0
    Хотя я на самом деле не знаю / не понимаю проблемную область, но мне кажется, что вам не нужно моделировать сами провода. Каждый компонент имеет свои указатели на другие компоненты, связанные с ним, и с помощью этого указателя он может получать информацию от этих подключенных компонентов. Для получения этой информации я, вероятно, попытался бы использовать полиморфные / виртуальные функции, которые может вызывать подключенный компонент, таким образом, пытаясь устранить необходимость знать точный тип для разыменования указателя.
  • 0
    проблема в том, как это с большим количеством классов stackoverflow.com/questions/5493745/… . Я не знаю заранее, какой класс будет иметь ссылку на какой класс. Булева схема была примером, я тоже сталкивался с этой проблемой ранее.
Теги:
class
design-patterns
design

1 ответ

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

Хотя я действительно не понимаю ваш вопрос/проблему полностью, ни проблемную область. Я предполагаю, что вы действительно не понимаете концепцию полиморфизма. Итак, чтобы проиллюстрировать эту концепцию здесь, пример.

input ----|  
power---relay1----|  
power----------relay2----Lamp 

Видя эту диаграмму сейчас, она, вероятно, не самая лучшая, но ее можно проиллюстрировать концепцией. Итак, что я хочу сделать здесь, это использовать relay1 в качестве входа в relay2, который заставит лампу гореть.. что-то вроде этого

#include <iostream>

struct Component {
    virtual void calculate(){};
    bool state;
};

struct Relay : public Component {
    Component* input;
    Component* power;
    Component* output;

    void calculate() {
        bool inputOn = input->state;
        bool hasPower = power->state;
        if (inputOn && hasPower) {
            this->state = true;
        } else {
            this->state = false;
        }
        output->calculate();
    }
};

struct Lamp : public Component {
    Component* input;

    void calculate() {
        this->state = input->state;
    }
};

int main(){

    Component input;
    input.state = true;

    Component power;
    power.state = true;

    Lamp lamp;
    lamp.state = false;

    Relay relay1;
    Relay relay2;

    relay1.input = &input;
    relay1.power = &power;
    relay1.output = &relay2;
    relay1.state = false;

    relay2.input = &relay1;
    relay2.power = &power;
    relay2.output = &lamp;
    relay2.state = false;

    lamp.input = &relay2;
    lamp.state = false;

    relay1.calculate();

    std::cout << "Lamp state = " << lamp.state;

    return 0;
}

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

Это очень рудиментарная реализация, но я надеюсь, что это поможет.

  • 0
    это помогло! Я только немного усложнил проблему. Эта «рекурсивная» функция вычисления хороша. :)
  • 1
    Это в основном древовидная структура, рекурсивный обход которой считается более "естественным" способом;) en.wikipedia.org/wiki/Tree_traversal#Types

Ещё вопросы

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