Указатели на функции-члены класса в C

#c

#c

Вопрос:

Я хочу вызвать функцию-член другого класса для объекта, но, похоже, я не могу понять, как это работает. В качестве примера кода о том, как это должно работать:

 Class A {
  void somefunction(int x);
}

Class B : A {
  void someotherfunction(int x);
}

Class C {
  void x() {
      callY(amp;ofthefunction); 
}   //here you call the function, you dont have an object yet,    and you don't know the argument yet, this will be found in function callY

  void Y(*thefunction) {
       find int x;
       if(something)
             A a = find a;
             a->thefunction(x);
       else 
             B b = find b;
             b->thefunction(x);
}
}
  

Я надеюсь, что это имеет смысл, также возможно разделить это на 2 метода, Y1 и Y2, но, поскольку 90% кода одинаковы (поиск объектов в файле XML), отличаются только объект и аргумент, где его сохранить, я бы хотел сделать это

Комментарии:

1. Вы надеетесь, что это имеет смысл? Нет, это не так. Опубликуйте хотя бы компилируемый код. Что мы должны предположить о ваших знаниях C , если ваш код даже не компилируется, с таким количеством синтаксических ошибок и всем прочим?

Ответ №1:

Вы можете использовать нечто, известное как виртуальная функция. Кстати, ваш синтаксис отвратителен, это class не Class , вам нужны фигурные скобки для ваших условных обозначений и разумное применение public , несколько дополнительных точек с запятой и т.д. Было бы полезно, если бы вы ознакомились с компилятором, прежде чем приходить сюда, понимаете.

 class A {
public:
  virtual void somefunction(int x);
};

class B : public A {
public:
  virtual void somefunction(int x);
};

void func(Aamp; a) {
    int x = 0;
    // Do something to find x
    a.somefunction(x); 
    // calls A::somefunction if this refers to an A
    // or B::somefunction if it's a B
}
int main() {
    A a;
    func(a); // calls A::somefunction
    B b;
    func(b); // calls B::somefunction
}
  

Комментарии:

1. Извините, я пытался написать псевдокод, а не фактический код C ? Возможно, я пытаюсь сделать это слишком сложным, дело в том, что в школе у меня есть уроки только C, а не C , поэтому я пытаюсь сделать это, вероятно, способом C. Это все равно не решит мою проблему, поскольку класс A в вашем примере имеет 2 практически идентичные функции, называемые truefunction и falsefunction, вот где возникает проблема, если бы я мог указать указатель на функцию вместо фактического указания имени в func (A amp; a), это было бы решено.

Ответ №2:

То, что вы хотите сделать, может быть сделано, хотя я бы не стал решать это таким образом:

 class A {
public:
    virtual int doit(int x) { return x 1; }
};

class B : public A {
public:
    int doit2(int x) { return x*3; }
    int doit(int x) { return x*2; }
};

int foo(int (A::*func)(int), int x, bool usea) {
    if (usea) {
        A a;
        return (a.*func)(x);
    } else {
        B b;
        return (b.*func)(x);
    }
}

int main() {
    int (A::*bla)(int) = amp;A::doit;
    foo(bla, 3, true);
    foo(bla, 3, false);

}
  

Однако, чтобы это сработало, должно выполняться следующее:

  1. Вы должны использовать указатели на функции базового класса (например, int (A::*bla)(int) ), иначе вы не сможете вызвать его в этом базовом классе (например, int (B::*bla)(int) может использоваться только в B экземплярах, а не в A инстансах, даже если метод уже определен в A ).
  2. У методов должны быть те же имена, что и в базовом классе
  3. Чтобы использовать переопределение (например, другой impl в производном классе), вы должны использовать virtual функции.

Но я бы предпочел пересмотреть ваш дизайн…

Комментарии:

1. Хороший чистый код, который работает. Хотя я не пробовал это кодировать, шаблоны C кажутся мне правильным подходом.

2. По поводу переосмысления моего дизайна: можно было бы просто сделать так, чтобы у меня были if else if и else, потому что у меня есть только 3 функции-члена в качестве опций (но с разными именами, к сожалению, поскольку класс A имеет 1 имя, а класс B имеет 2 других имени, но с аналогичными результатами)! Но мне было просто любопытно, можно ли это сделать так, как я прошу, учитывая, что я пришел из C coding, где это было бы легко

Ответ №3:

Нет, это вообще не сработает. Указатель на элемент A всегда будет указывать на эту функцию, даже когда она вызывается в B, потому что B наследует от A.

Вам необходимо использовать виртуальные функции. Я вижу, что DeadMG опередил меня в этом.