2013-08-23 4 views
1

В настоящее время я изучаю динамические привязки и виртуальные функции. Это от ускоренного 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!" 
} 

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

0

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

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

То есть, вероятно, _way_ выше уровня ФПА, учитывая вопрос ОП спросил. –

+0

Тем не менее, мой пример проще, чем ваш, но все равно передает его эффективно :) – Arun