Я работаю над небольшим проектом, и я оказался в такой ситуации:
class A{}
class B : class A {
public:
void f();
int getType() const;
private:
int type;
}
class C : class A{
public:
int getType() const;
private:
int type;
}
Я хочу знать, есть ли способ вызвать функцию f()
(in class B
) из объекта type A
?
Я пробовал это, но он говорит, что функция f()
не может быть найдена в class A
:
int main(){
vector<A*> v;
// v initialized with values of A ...
if (v->getType() == 1){ // 1 is the type of B
v->f();
}
}
Как вы видели, этот код не скомпилируется, потому что у A
нет метода f
. Чтобы заставить его работать, вам нужно явно понизить указатель:
B* tmp = dynamic_cast<B*>(v);
tmp->f();
я не думаю, что это решит первоначальную проблему, поскольку динамический состав не должен быть известен (например, это вполне может быть класс C вместо B)
@НикосМ. но у C
нет f
так что актерский состав проваливается и все в порядке... (может быть if (tmp) tmp->f();
было бы лучше)
хорошо, но все же я думаю, что это не выход, но я не ОП
OP реализовал свой собственный механизм проверки типов — этому предшествует if (v->getType() == 1)
Начнем с того, что с вашими текущими классами вы не можете ставить getType()
на A*. Потому что интерфейс A не имеет этого метода. Чтобы решить эту проблему, нужно либо сделать getType
виртуальной функцией в A, либо переместить поле type
в базовый класс A (как protected
) и инициализировать его в конструкторах дочерних классов. Позвольте мне показать вам первый метод, потому что я думаю, что это лучший подход, поскольку он делает цель этой функции более ясной.
class A {
public:
virtual int getType() { return 0; } // or delete the function: ... getType() = 0;
}
class B : public A {
public:
int getType() override { return 1; }
}
С этими классами, как только вы создаете экземпляр B, getType() возвращает 1 при вызове этого экземпляра, независимо от того, указывает ли на него A*
или B*
:
A *object = new B();
object->getType(); // returns 1
Теперь, если вам нужно получить доступ к f()
из B, вы можете снова добавить его как виртуальный метод к интерфейсу A или сделать приведение к B*
.
Используя виртуальный метод:
class A {
public:
virtual void f() { /* a default action maybe? */ }
}
class B : public A {
public:
void f() /* override if you want */ { /* whatever this function does in B */ }
}
...
for (A *ptr : v)
ptr->f();
Использование приведения:
class A {
public:
virtual int getType() { return 0; }
}
class B : public A {
public:
void f();
int getType() override { return 1; }
}
...
for (A *ptr : v)
if (ptr->getType() == 1)
dynamic_cast<B*>(ptr)->f();
похоже вы подходите к проблеме с неправильным подходом, наследование в ООП так не работает. Лучше объясните свою первоначальную проблему, которая привела к этому маршруту