#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);
}
Однако, чтобы это сработало, должно выполняться следующее:
- Вы должны использовать указатели на функции базового класса (например,
int (A::*bla)(int)
), иначе вы не сможете вызвать его в этом базовом классе (например,int (B::*bla)(int)
может использоваться только вB
экземплярах, а не вA
инстансах, даже если метод уже определен вA
). - У методов должны быть те же имена, что и в базовом классе
- Чтобы использовать переопределение (например, другой impl в производном классе), вы должны использовать
virtual
функции.
Но я бы предпочел пересмотреть ваш дизайн…
Комментарии:
1. Хороший чистый код, который работает. Хотя я не пробовал это кодировать, шаблоны C кажутся мне правильным подходом.
2. По поводу переосмысления моего дизайна: можно было бы просто сделать так, чтобы у меня были if else if и else, потому что у меня есть только 3 функции-члена в качестве опций (но с разными именами, к сожалению, поскольку класс A имеет 1 имя, а класс B имеет 2 других имени, но с аналогичными результатами)! Но мне было просто любопытно, можно ли это сделать так, как я прошу, учитывая, что я пришел из C coding, где это было бы легко
Ответ №3:
Нет, это вообще не сработает. Указатель на элемент A всегда будет указывать на эту функцию, даже когда она вызывается в B, потому что B наследует от A.
Вам необходимо использовать виртуальные функции. Я вижу, что DeadMG опередил меня в этом.