Переопределение наследования - PullRequest
0 голосов
/ 06 февраля 2019

У меня есть вопрос относительно раннего / позднего связывания во время переопределения наследования.

Итак, я перехожу основы OOP для C ++ и читаю, что если вы не объявляете функцию в базовом классе virtual, выне могу отменить это.Однако у меня есть следующий код, и похоже, что мой компилятор переопределяет его для меня в любом случае.

#include <iostream>

using namespace std;

class Book{
public:
    string title;
    int number;

    Book(){
    }

    Book(string title){
        cout << "book " << title << " created" << endl;
    }

    void setNumber(int num){
        number = num + 7;
    }

    ~Book(){
        cout << "book " << title << " destroyed:";
    }
};

class Magazine: public Book {
public:

    void setNumber(int num){
    number = num;
    }
};

int main()
{
    Magazine mag;
    mag.setNumber(4);
    cout << mag.title << endl;
    cout << "the number you are looking for is: " << mag.number << endl;
}

вывод на моем компиляторе равен 4, но на основании того, что я прочитал, c ++ имеет раннее связывание, и еслифункция не объявлена ​​виртуальной в базовом классе, ее нельзя переопределить, поэтому она должна вывести num + 7, как указано в базовом классе.Я просто получил неправильный ресурс?Или это может быть ошибка / аномалия в моем компиляторе?

Спасибо всем за помощь

Ответы [ 4 ]

0 голосов
/ 06 февраля 2019

Вы не отменяете свою функцию.Все, что вы делаете, это переопределение

Если вы хотите быть уверены, что вы переопределили функцию, поставьте ключевое слово override после объявления функции, чтобы увидеть, действительно вы переопределяете или нет.

Пример:

void suspicious() override; - (функция C ++ 11)

Также полезно знать, если вы переопределите функцию «какую функцию использовать (проверка типа)» происходит во время компиляции, и если вы объявляете свою функцию виртуальной с тем же именем, это происходит во время выполнения с помощью механизма виртуальных таблиц.

0 голосов
/ 06 февраля 2019

Вы можете "переопределить" не виртуальные функции, но реализация будет не динамически, а статически.Вы поймете разницу в сочетании с полиморфизмом:

Book* mag = new Magazine();
mag->setNumber(4);
cout << mag->title << endl;
cout << "the number you are looking for is: " << mag->number << endl;

Это вызовет Book -имплементации, тогда как, когда вы объявили функции-члены виртуальными, они будут динамически связаны с реализацией Magazines.

0 голосов
/ 06 февраля 2019

Ключевое слово virtual действительно вступает в игру только тогда, когда вы имеете дело с полиморфизмом.И это происходит только тогда, когда у вас есть указатели / ссылки.

Если вы вместо этого сделали что-то вроде:

int main()
{
    Magazine mag;
    Book *b = &mag;
    b->setNumber(4);
    cout << b->title << endl;
    cout << "the number you are looking for is: " << b->number << endl;
}

Вы увидите, что мы в конечном итоге вызываем Book::setNumber(), даже если мывы на самом деле указываете на Magazine!

Если вы объявите setNumber как функцию virtual и запустите приведенный выше код, вы будете использовать динамическое связывание функций.Поэтому вместо немедленного вызова Book::setNumber(), поскольку у нас есть указатель Book, программа будет динамически проверять, чтобы увидеть, на что действительно указывает b.Так как на самом деле это Magazine объект, мы затем вызовем Magazine::setNumber().Это магия полиморфизма.

0 голосов
/ 06 февраля 2019

Вместо того, чтобы пытаться объяснить, я рекомендую вам попробовать следующий эксперимент:

Book &book = Mag;
book.setNumber(4);
cout << mag.number << endl;

А затем повторите это с Book::setNumber объявленным virtual.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...