2014-02-25 2 views
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's 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's output: ->bin-------> 
    bout.input = &w1; //output wire connected to boolean output's input:   ------->bout-> 

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

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

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

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

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

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

    return 0; 
}; 

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

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

+0

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

+0

проблема такая, как это, с большим количеством классов http: // stackoverflow .com/вопросы/5493745/с-связь-2-классы-вместе-хау. Я заранее не знаю, какой класс будет иметь ссылку на какой класс. Булевская схема была примером, я столкнулся с этой проблемой и раньше. –

ответ

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

Это, в основном, структура дерева, пересекающая ее рекурсивно, считается более «естественным» способом;) http://en.wikipedia.org/wiki/Tree_traversal#Types –

Смежные вопросы