Как тип объекта может быть неизвестен во время компиляции?

В настоящее время я изучаю динамическое связывание и виртуальные функции. Это из Ускоренного C ++, глава 13:

[…] Мы хотим принять это решение во время выполнения. То есть мы хотим
Система для запуска правильной функции на основе фактического типа
объекты передаются в функцию, которая известна только во время выполнения.

Я не понимаю саму идею, что тип объекта может быть неизвестен во время компиляции. Разве это не очевидно из исходного кода?

1

Решение

Не за что. Рассмотрим этот пример:

struct A {
virtual void f() = 0;
};

struct B : A {
virtual void f() { std::cerr << "In B::f()\n"; }
};

struct C : A {
virtual void f() { std::cerr << "In C::f()\n"; }
};

static void f(A &a)
{
a.f(); // How do we know which function to call at compile time?
}

int main(int,char**)
{
B b;
C c;
f(b);
f(c);
}

Когда глобальная функция f компилируется, нет способа узнать, какую функцию он должен вызывать. На самом деле, каждый раз нужно будет вызывать разные функции. Первый раз это называется f(b)нужно будет позвонить B::f()и второй раз он вызывается с f(c) это нужно будет позвонить C::f(),

1

Другие решения

C ++ имеет концепцию указатели, где переменная содержит только «дескриптор» фактического объекта. Тип реального объекта неизвестен во время компиляции, только во время выполнения. Пример:

#include <iostream>
#include <memory>

class Greeter {
public:
virtual void greet() = 0;
};

class HelloWorld : public Greeter {
public:
void greet() {std::cout << "Hello, world!\n";}
};

class GoodbyeWorld : public Greeter {
public:
void greet() {std::cout << "Goodbye, world!\n";}
};

int main() {
std::unique_ptr<Greeter> greeter(new HelloWorld);
greeter->greet();    // prints "Hello, world!"greeter.reset(new GoodbyeWorld);
greeter->greet();    // prints "Goodbye, world!"}

Смотрите также: ответ Вона Катона, который использует Рекомендации (это еще один способ удерживать дескриптор объекта).

1

Скажем, у вас есть указатель на базовый класс, указывающий на производный объект

Base *pBase = new Derived;

// During compilation time, compiler looks for the method CallMe() in base class
// if defined in class Base, compiler is happy, no error
// But when you run it, the method call gets dynamically mapped to Derived::CallMe()

// ** provided CallMe() is virtual method in Base and derived class overrides it.

pBase->CallMe(); // the actual object type is known only during run-time.
0
По вопросам рекламы [email protected]