LINUX.ORG.RU

C++ как применить метод у нужному объекту?


0

0

Привет всем.
Сразу к делу. Есть несколько классов: Class1, Class2, Class3.
Соответственно есть и 3 объекта: obj1, obj2, obj3 от этих класов.
У каждого объекта есть одинаковые методы: method_a(), method_b(), method_c().
То есть к каждому объекту ( obj1, obj2, obj3 ) можна применить любой из этих метов, они у них все есть, лишь результат будут давать разный.
Проблема в следуещем.
Как приметить метод ( напр. method_a() ) к _необходимому_ объекту?
Напр.

std::string needObj;
...
// для метода method_a()
if ( needObj == "objectOne" ) {
obj1 -> method_a();
} else if ( needObj == "objectTwo" ) {
obj2 -> method_a();
} else if ( needObj == "objectThree" ) {
obj3 -> method_a();
}
...
и так далее...

Как видно это очень догло и много писанины. Тем более что у меня таких ф-ций будет много.
Можно как либо это организовать нормально?

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

void * ф-ция тоже не подходит, как как придеться делать static_cast сново же писать эти циклы....

Есть ли какой-либо нормальный способ огранизовать это перебор нужного объекта с вызовом нужного метода в виде ф-ции или еще как-то?

anonymous

Очень похоже что нужно сделать один родительский класс и перегрузить один метод в разных потомках, единственная проблема в возвращаемом значении. Сложно понять, что вы хотите делать, но вероятнее всего вы это как-то криво делаете...

anonymous
()

сделай интерфейс

struct if_a {
 virtual void method_a () ;
}

потом унаследуйся

class Class1 : public if_a {
 ...
}

ну а далее спокойно вызывай

generatorglukoff ★★
()

> Как приметить метод ( напр. method_a() ) к _необходимому_ объекту

К объекту определенного класса или к конретному объекту?

Если объекту определенного класса, то нужно просто воспользоваться полиморфизмом: классы Class1, Class2, Class3 сделать потомками одного класса Class, у которого эти методы виртуальные. В потомках их реализовать. Тогда вызывая метод, он будет вызываться в контексте нужного тебе класса, т.е. в зависимости от того, с объектом какого класса первоначально имелось дело.

smh ★★★
()
Ответ на: комментарий от Legioner

> Угу.

std::map то это угу. А почему строка отображается в указатель на класс? Нужно отображать в указатель на метод базового класса.

dilmah ★★★★★
()
Ответ на: комментарий от dilmah

Метод один и тот же. Разные объекты.

Правда я топикстартера не до конца понял. Если ему надо и по объекту и по функции различать, то тогда конечно пару <object, function> нужно хрнаить.

Legioner ★★★★★
()
Ответ на: комментарий от svu

>Либо базовый класс. Либо ... никак.

+1 зачем map непонятно... да я тупой

dimon555 ★★★★★
()

Все решил проблему. Она простая как валенок.
Спасибо огромное всем кто помогал. Толкнули меня в правильную сторону - в наследование.
И так. Если охарактизовать проблему в общем, то можна так: как сделать чтобы неякая ф-ция возращала значение одного типа при разных объктах с разных класов.

Короче наследование в самый раз.
Я создаю неякий клас родителя, скажем ClassPapa.
Далее в класе ClassPapa создаем все нужные нам ф-ции:

ClassPapa {
virtual method_a() { .. }
virtual method_b() { .. }
virtual method_c() { .. }
...
}

потом все остальные класы наследуются от него:

class Class1 : public ClassPapa {
...

class Class2 : public ClassPapa {
...

class Class3 : public ClassPapa {
...

Потом остаються пустяки:

std::map < std::string, ClassPapa * > myObj;

objs [ "someObj1" ] = new Class1;
objs [ "someObj2" ] = new Class2;
objs [ "someObj3" ] = new Class3;

и теперь в зависимости от того какой метод надо подставить под вызов ф-ции:

std::string needObj;
...

// в зависимости от needObj подставляется уже нужный объект
myObj [ needObj ] -> method_a();
myObj [ needObj ] -> method_b();
myObj [ needObj ] -> method_c();
...

Весь сыр-бор из-за того, что разные класы возращают разные типы соответственно.
А вот если наследовать, то тип будет один - предок ( ClassPapa ), а в этот указатель уже записываем все что нам нуно, напр:

ClassPapa * pObj = new Class1;
или
ClassPapa * pObj = new Class1;
и т.д.

Все. Спасибо еще раз всем. Тема закрыта.

anonymous
()
Ответ на: комментарий от anonymous

поправочка: всесто objs должно быть myObj

anonymous
()

Создать виртуальный родительский класс, отнаследоваться от него. Тогда в зависимости от типа указателя (ClassA* ptrA, ClassB* ptrB, ClassC* ptrC) будут вызываться методы нужного класса. В родительском классе не забудь сделать виртуальным деструктор.

one_more_hokum ★★★
()
Ответ на: комментарий от svu

>Либо базовый класс. Либо ... никак. Ибо рефлексии нет. Не то что жабка.

4.2 : статический полиморфизм что, уже отменили ?

jtootf ★★★★★
()

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

template <typename T> void f(T & obj)
{
    obj.method_a();
    obj.method_b();
    obj.method_c();
}

либо позднее связывание, через явные интерфейсы - про
это тут уже и так достаточно наговорили...

jtootf ★★★★★
()

>Шаблоны не подходят так как им надо как раз передавать _нужный_ объект, и значит что всю писанину эту мне придеться сново писать. Перебор в шаблони сделать не получится, так как ему сново же нужно передавать объект в качестве параметра

смею обратить твоё внимание, что для шаблонов функций в C++ работает механизм автоматического выведения типа. и, к слову, "перебор в шаблоне" сделать тоже можно (хоть в данном случае и не нужно) - посредством рекурсии, ибо язык шаблонов C++ вообще говоря функциональный

jtootf ★★★★★
()

в самом крайнем случае (не рекомендуется делать это, если можно заменить на шаблоны или полиморфизъм):

typedef boost::function<void ()> Callback;
typedef std::map<std::string, Callback> Callbacks;

Callbacks callbacks;
boost::shared_ptr<ObjectOne> obj1(new ...);
boost::shared_ptr<ObjectTwo> obj2(new ...);

callbacks.insert(Callbacks::value_type("objectOne"), boost::bind(&ObjectOne::method_a, obj1));
callbacks.insert(Callbacks::value_type("objectTwo"), boost::bind(&ObjectTwo::method_a, obj2));
...

const Callbacks::const_iterator it = callbacks.find(needObj);
if(it != callbacks.end()){
  it->second();
}

Но следует помнить, что boost::function и boost::bind - не такие быстрые как стандартные решения.

stpg
()
Ответ на: комментарий от stpg

>в самом крайнем случае...

при всём уважении, это - вырезание гландов автогеном через...ну, понятно. дальше остаётся только предложить написать препроцессор на scheme, который нужный код сгенерирует

jtootf ★★★★★
()
Ответ на: комментарий от jtootf

> смею обратить твоё внимание, что для шаблонов функций в C++ работает механизм автоматического выведения типа

ну cмотри -- чтобы этот механизм сработал, нужно чтоб статический тип на этапе компиляции был известен -- дальше понимаешь?

только наследование здесь будет работать

dilmah ★★★★★
()
Ответ на: комментарий от dilmah

предложение решать шаблонами здесь абсурдно -- ему нужно рантаймовое динамическое значение превратить в вызов -- а шаблоны трабатывают и фиксируются при компиляции

dilmah ★★★★★
()
Ответ на: комментарий от dilmah

>ну cмотри -- чтобы этот механизм сработал, нужно чтоб статический тип на этапе компиляции был известен

и какое место в приведённом мною коде работать не будет ?

>только наследование здесь будет работать

признайся, тебя укусил java-программист ?

jtootf ★★★★★
()
Ответ на: комментарий от dilmah

>ему нужно рантаймовое динамическое значение превратить в вызов

и где в постановке задачи требование "рантаймовости", а ? требование - избежать дублирования кода; по эффективности тут вопрос количество джампов против обьёма обьектного файла

jtootf ★★★★★
()
Ответ на: комментарий от dilmah

>поведение задается в std::string

и что сия фраза должна означать ?

jtootf ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.