У меня есть следующий код c ++ 11, который работает, хотя я ожидал, что он потерпит крах или даже не скомпилируется. Получение указателя на чисто виртуальную функцию-член должно возвращать нулевой или недействительный указатель или должно быть заблокировано компилятором. Я хотел бы понять, почему это работает.
Я знаю, что есть другие (лучшие) способы кодирования этого, это чисто теоретический вопрос для понимания того, что делает синтаксис.
#include <iostream>
#include <functional>
class Abstract
{
public:
void foo()
{
auto func = std::bind(&Abstract::virtualFoo, this);
func();
}
protected:
virtual void virtualFoo() = 0;
};
class Derived1 : public Abstract
{
private:
void virtualFoo() override
{
std::cout << "I am Derived1\n";
}
};
class Derived2 : public Abstract
{
private:
void virtualFoo() override
{
std::cout << "I am Derived2\n";
}
};
int main(int argc, char *argv[])
{
Abstract * a1 = new Derived1;
Abstract * a2 = new Derived2;
a1->foo();
a2->foo();
return 0;
}
Цель вполне понятна, в функции базового класса foo () я хочу получить указатель на производные виртуальные функции.
Однако, насколько я понимаю, он не должен работать и даже не должен компилироваться с чисто виртуальной функцией. При использовании не чистой виртуальной функции она должна выполнять функцию базового класса. Но я был очень удивлен, увидев, что он компилируется и выдает намеченный результат: он печатает «I am Derived1», затем «I am Derived2»
Как &Abstract::virtualFoo
может вернуть действительный указатель, даже не зная указателя на фактический объект, обязательный для доступа к vtable ???
Онлайн C ++ ссылка: https://onlinegdb.com/SJfku8rvV
Для меня действительный синтаксис должен быть:
auto func = std::bind(&this->virtualFoo, this);
В качестве разыменования this
должен фактически получить доступ к vtable и вернуть указатель на функцию. Но с ++ 11 так не думает.