2010-09-16 4 views
0

Я что-то испортил. Вот код:проблема наследования

#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) должен использовать это соединение (он будет сериализован)
  • .. Кроме того, каждый экземпляр должен регистрировать отдельный обратный вызов

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

+1

Я в замешательстве - вы не определили никаких отношений наследования. –

+1

+1. И каков фактический вопрос/проблема в нем? – dyp

ответ

1

Ваш код создает копию вашего объекта соединения для каждого экземпляра. Исходный объект соединения затем доступен только вашим 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

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

0

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

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

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

3) Постарайтесь использовать константу и ссылку как можно больше (т. Е. Конструктор connection_c). Будет создано меньше объектов-конструкторов/temp-объектов.

#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

вы можете добавить одно: не использовать обратные вызовы, они злые (при использовании в качестве указателей). Вместо этого используйте наследование или шаблоны. Я не вижу причин для обратных вызовов здесь. Кроме того, векторная версия не очень OOP imho. Да, это просто, но не _intuitive_. Вы должны заботиться о векторе все время и итерации для каждого использования выполнения. Тип, который обертывает это, будет простым и адекватным imho. – dyp

+0

@DyP - Могло определенно обернуть вектор. Тем более, что он содержит указатели. Класс с шаблоном RAII был бы неплохо помочь с очисткой. Не уверен, для чего обратный вызов в этом случае, но обратные вызовы определенно имеют место в этом мире. – skimobear

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