我目前正在學習動態綁定和虛函數。這來自Accelerated C++,第13章:在編譯時如何識別對象類型?
[...]我們想在運行時做出這個決定。也就是說,我們希望 系統根據傳遞給該函數的實際類型來運行正確的函數,該函數僅在運行時已知。
我不明白在編譯時對象的類型可能未知的想法。源代碼不明顯嗎?
我目前正在學習動態綁定和虛函數。這來自Accelerated C++,第13章:在編譯時如何識別對象類型?
[...]我們想在運行時做出這個決定。也就是說,我們希望 系統根據傳遞給該函數的實際類型來運行正確的函數,該函數僅在運行時已知。
我不明白在編譯時對象的類型可能未知的想法。源代碼不明顯嗎?
根本不是。考慮下面這個例子:
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()
。
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!"
}
參見:沃恩卡託的答案,它採用引用(這是另一種方式來保存的句柄對象)。
假設你有一個指向基類指向派生類對象
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.
那很可能是_方式_的OP的水平之上,鑑於問題的任擇議定書的要求。 –
儘管如此,我的例子比你的更簡單,但仍然有效地傳達了它:) – Arun