Различные функции?

Итак, вот пример кода. Задача заключалась в том, чтобы выдать результат, который будет распечатывать этот код. Это 2 разные функции? Что тогда происходит с vtable в классе B? Он просто хранит 2 указателя на 2 разные функции с одинаковым именем?

#include<iostream>
#include <vector>
using namespace std;
class A
{
public:
    A()
    {
        init();
    }
    virtual void init(bool a = true)
    {
        if(a)
            cout << "A" << endl;
    }
};
class B :public A
{
public:
    virtual void init()
    {
        cout << "B" << endl;
    }
};

int main()
{
    B b;
    A* a = &b;
    a->init();
    a->init(true);
    system("pause");
}

Не могу найти, где прочитать об этом деле. Не могли бы вы, товарищи, объяснить или дать ссылку на какой-нибудь источник, если вы видели этот случай?


person Edwin Paco    schedule 13.11.2018    source источник
comment
Попробуйте скомпилировать его с включенными предупреждениями - вы должны получить хотя бы одно полезное предупреждение, которое даст вам некоторое представление ...   -  person Paul R    schedule 13.11.2018
comment
@PaulR GCC хранит молчание.   -  person HolyBlackCat    schedule 13.11.2018
comment
О, лязг, очевидно, более полезен, чем ... <stdin>:21:18: warning: 'B::init' hides overloaded virtual function [-Woverloaded-virtual] virtual void init() ^ <stdin>:12:18: note: hidden overloaded virtual function 'A::init' declared here: different number of parameters (1 vs 0) virtual void init(bool a = true)   -  person Paul R    schedule 13.11.2018
comment
Это причина override.   -  person molbdnilo    schedule 13.11.2018
comment
FWIW MSVC ++ также выдает предупреждение. Однако ни gcc, ни ICC этого не делают.   -  person Paul R    schedule 13.11.2018
comment
Каждая функция, которую вы пишете, отличается от других. Настоящий вопрос: «Когда я звоню, какой из них выбран?»   -  person Jean-Baptiste Yunès    schedule 13.11.2018
comment
Не используйте глупый system("pause");, если хотите, чтобы окно оставалось открытым. Вместо этого используйте «Начать без отладки» (Ctrl + F5).   -  person harper    schedule 13.11.2018
comment
@PaulR gcc выдаст предупреждение, если вы явно добавите переключатель -Woverloaded-virtual, который вы указали в предупреждающем сообщении clang.   -  person Pates    schedule 13.11.2018


Ответы (1)


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

Помните, что имя функции - это только часть ее идентичности! Его список параметров тоже имеет значение.

Если вы поместите ключевое слово override в B::init(), тогда ваша программа не сможет скомпилироваться, потому что B::init() на самом деле ничего не отменяет (в его основе нет init(), виртуального или другого).

На самом деле с vtable ничего не «происходит», чего бы не произошло, если бы две функции буквально имели разные имена, например A::init(bool) и B::urgleburgleboop().

Обратите внимание, что помимо virtual, полиморфизма и переопределения, B::init() также «скрывает» A::init(bool) для нормального разрешения перегрузки (спасибо, C ++!), И из-за этого Clang предупредит о вашем коде.

Что касается того, где вы можете прочитать об этом, ваша книга C ++ будет хорошим началом. :)

person Lightness Races in Orbit    schedule 13.11.2018
comment
Хороший ответ, я писал один с использованием nm и показывал, что искаженные символы различны для двух сигнатур методов, но теории здесь достаточно. - person Tezirg; 13.11.2018