C++ Как вызвать дочерний метод из родительского

Я работаю над небольшим проектом, и я оказался в такой ситуации:

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();
    }
}

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

Nikos M. 26.12.2020 12:15
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
407
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Как вы видели, этот код не скомпилируется, потому что у A нет метода f. Чтобы заставить его работать, вам нужно явно понизить указатель:

B* tmp = dynamic_cast<B*>(v);
tmp->f();

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

Nikos M. 26.12.2020 12:18

@НикосМ. но у C нет f так что актерский состав проваливается и все в порядке... (может быть if (tmp) tmp->f(); было бы лучше)

463035818_is_not_a_number 26.12.2020 12:21

хорошо, но все же я думаю, что это не выход, но я не ОП

Nikos M. 26.12.2020 12:23

OP реализовал свой собственный механизм проверки типов — этому предшествует if (v->getType() == 1)

Mureinik 26.12.2020 12:30

Начнем с того, что с вашими текущими классами вы не можете ставить 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();

Другие вопросы по теме