проблема наследования - PullRequest
       8

проблема наследования

0 голосов
/ 17 сентября 2010

Я что-то напутал. Вот код:

#include <iostream>

class connection_c {
  private:
    std::string data_;
    void (*saveCallBack_)();
  public:
    connection_c(std::string &data) : data_(data) { std::cout << "ctor: " << __FUNCTION__ << ":" << data_ << std::endl;}
    void registerCallBack(void(*cb)()) { saveCallBack_ = cb; }
};

class inst_c {
  private:
    static int id;
    connection_c conn;
    static void cb() { std::cout << __FUNCTION__ << " id = " <<  id << std::endl; } 
  public:
    inst_c(connection_c &c, int a) : conn(c),  id(a)  { 
      std::cout << "ctor: " << __FUNCTION__ << " " << id << std::endl;
      conn.registerCallBack(&cb); 
    }
};

class group_inst_c {
  private:
    connection_c conn;
    inst_c i,j,k;
  public:
    group_inst_c(std::string data) : conn(data), i(conn,1), j(conn,2), k(conn,3) {} 
};


int main() {
  group_inst_c gi("asdf");
  return 0;
}

Чего я хочу достичь;)

  • создать группу экземпляров (group_inst_c)
  • он должен инициализировать одно соединение для группы (connection_c)
  • каждый экземпляр (inst_c) должен использовать это соединение (оно будет сериализовано)
  • .. кроме того, каждый экземпляр должен регистрировать отдельный обратный вызов

Конечно, я перепутал с клонированием, но, наверное, не только. Может кто-нибудь помочь мне решить эту загадку? ТНХ.

Ответы [ 3 ]

1 голос
/ 17 сентября 2010

Ваш код создает копию вашего объекта подключения для каждого экземпляра. Исходный объект подключения будет доступен только вашим group_inst_c. Это то, что вы хотите? Если нет, вам нужно изменить:

class inst_c {
  private:
    static int id;
    connection_c& conn; // <-- Needs to be a reference.

кроме того, каждый экземпляр должен регистрировать отдельный обратный вызов

Я не уверен, что вы имеете в виду здесь. Должны ли обратные вызовы быть функциями-членами? Затем вам нужно использовать «указатель на функцию-член» (операторы ::*, .* и ->*). Если предполагается, что обратные вызовы являются обычными функциями, вы должны быть в порядке с вашим текущим кодом. Вам просто нужно добавить это к class connection_c:

void doCallback(void) { (*saveCallBack_)(); }
0 голосов
/ 17 сентября 2010

Сначала постарайтесь сделать все просто. В дальнейшем всегда есть возможность вырастить / улучшить дизайн. Ниже приведен пример кода, и вот несколько вещей, о которых я думал при его создании:

1) Как уже упоминалось, будь проще. Например, может быть, концепция группы может быть вектором (то есть inst_group_t) для запуска. Вы всегда можете вырастить дизайн позже, когда узнаете больше о нем.

2) Попробуйте уменьшить классовые зависимости. Например, может быть, мне не нужно иметь соединение в качестве переменной-члена. Я могу передать его, когда это необходимо (то есть execute ()). Возможно, обратный вызов не нужно регистрировать (т.е. execute ()), поскольку его 1 connection_c для многих экземпляров inst_c, регистрирующих обратный вызов для каждого inst_c, будет означать, что соединение будет иметь некоторый контейнер. Будьте проще :)

3) Старайтесь использовать как можно больше const и reference (т.е. конструктор connection_c). Будет создано меньше копий конструкторов / временных объектов.

#include <iostream>

class connection_c {
  private:
    std::string data_;
  public:
    connection_c(const std::string &data) : data_(data) { 
        std::cout << "ctor: " << __FUNCTION__ << ":" << data_ << std::endl;
    }
};

class inst_c {
  private:
    int id;
  public:
    inst_c(int a) : id(a)  { 
      std::cout << "ctor: " << __FUNCTION__ << " " << id << std::endl;
    }

    typedef void (*execute_callback_t)(int i);
    void execute(connection_c& connection, execute_callback_t callback) {
        callback(id);
    }
};

void mycallback(int id) {
    std::cout << "Instance number " << id << " executed" << std::endl;
}

int main() {

    typedef std::vector<inst_c*> inst_group_t;
    inst_group_t group;

    std::string data;
    connection_c connection(data);

    for (int i = 0; i < 10; ++i) 
        group.push_back(new inst_c(i) );

    for (int i = 0; i < 10; ++i) 
        group[i]->execute(connection, mycallback);

    for (int i = 0; i < 10; ++i) 
        delete group[i];

    return 0;
}
0 голосов
/ 17 сентября 2010

Если я правильно понял (вы хотите вызвать несколько обратных вызовов из одного соединения [объекта]), вам нужен список в connection_c для регистрации обратных вызовов (точно так же, как делегаты в C #, если вы их знаете).
Если событие происходит с этим соединением, оно должно знать, куда сообщать. Таким образом, вы должны как-то перебирать обратные вызовы (вызывать их один за другим; вы не можете вызывать их все сразу). Самый простой и простой способ - это использовать список STL или, возможно, предложить что-то подходящее.
Взгляните на это: Класс делегата C ++ . В основной функции определен вектор, который принимает несколько обратных вызовов. Вы можете использовать этот шаблон в своем классе connection_c для добавления , а не для установки обратного вызова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...