C ++ Вызов производной функции из экземпляра базового класса - PullRequest
7 голосов
/ 02 апреля 2012

Я довольно новичок в C ++, но столкнулся с проблемой, которую не могу решить.Я буду использовать автомобили, чтобы проиллюстрировать проблему, просто чтобы все было проще.Итак, давайте скажем, что у меня есть автомобиль базового класса, и у меня есть разные бренды, которые наследуют от этого класса.Вот так:

class Car
{
    public:
       Car();
};

class Ford: public Car
{
    public:
        Ford();
        void drive();
        void park();
};

Вся идея состоит в том, чтобы собрать все эти разные автомобили в единый вектор типа Car.Вот так:

vector<Car*> cars;
cars.push_back(new Ford());
cars.back()->drive(); //this won't work

Как я могу вызвать производную функцию на экземпляре базового класса?Обратите внимание, что я хочу поместить все это в один вектор.Причина этого заключается в том, что я хочу использовать только последний добавленный экземпляр производного класса автомобиля (в данном случае производный класс автомобиля ford).Также обратите внимание, что все классы автомобилей будут иметь одинаковые функции.

Ответы [ 6 ]

7 голосов
/ 02 апреля 2012

Если эти функции действительно общие для всех производных классов, то у вас есть общий интерфейс, поэтому вы должны выразить это через базовый класс. Для этого вы объявляете эти функции чисто виртуальными:

class Car {
public:
    virtual void drive() = 0;  // Pure-virtual function
};

class Ford : public Car {
public:
    virtual void drive() { std::cout << "driving Ford\n"; }
};

...

vector<Car*> cars;
cars.push_back(new Ford());
cars.back()->drive(); //this will work

[ В дополнение к этому, обычно считается плохой практикой иметь вектор необработанных указателей, потому что это затрудняет управление памятью. Вы должны рассмотреть возможность использования умных указателей. ]

3 голосов
/ 02 апреля 2012

У вас есть два варианта: либо добавить метод виртуального привода () в определение вашего автомобиля, либо привести указатели автомобилей к указателям Ford. Скорее всего, вы захотите сделать первый.

class Car
{
    public:
       Car();
       virtual void drive() { // default implementation}
};

Теперь вы можете управлять () вашим автомобилем! Вы также можете сделать drive () чисто виртуальной функцией, например:

class Car
{
    public:
       Car();
       virtual void drive() = 0;
};

Это в основном означает, что для drive () реализации по умолчанию нет: она ДОЛЖНА быть переопределена в подклассе. Второй способ, который я упомянул, который, опять же, вы, вероятно, не хотите, но должен быть включен для полноты, это приведение указателя:

static_cast<Ford*>(cars.back())->drive();

Это работает только в том случае, если вы заранее знаете, что Автомобиль - это Форд, и в этом сценарии его мало используют. Вы также можете посмотреть в dynamic_cast.

2 голосов
/ 02 апреля 2012

Если все Car классы имеют одинаковые функции, тогда объявите их как чистые virtual в базовом классе Car:

class Car
{
public:
    Car();
    virtual ~Car();
    virtual void drive() = 0;
    virtual void park()  = 0;
};

Это позволит примеру кода, который использует vector дляработа как отправлено.

0 голосов
/ 02 апреля 2012

Вы должны поставить виртуальную функцию.

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

Вы можете найти faq (или учебник) о виртуальных функциях здесь:

http://www.parashift.com/c++-faq-lite/virtual-functions.html

0 голосов
/ 02 апреля 2012

Вы должны определить интерфейс как:

class Car{
public:
 Car();
 virtual void moveForward(unsigned int speed) = 0;
 virtual void moveBack(unsigned int speed) = 0;
 //...
 virtual ~Car();
};

Не забудьте сделать виртуальный деструктор.После этого вам просто нужно реализовать эти методы в ваших дочерних классах и вызывать их после.Также в векторе вы можете использовать shared_ptr или просто передать экземпляры напрямую.

0 голосов
/ 02 апреля 2012

Может быть, если возможно, вы можете определить базовый класс как

class Car
{
    public:
       Car();
       virtual void drive();
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...