We say that the call of virtual function in C++ is determined in run time, not in compile time. So I think I am not clear about the difference between compile time and run time. In my rough thought, everything should be determined in compile time... Who could help on this question? Thanks！

The compiler cannot decide whether in bp->func() the function of the base class or that of the derived class is called, because it depends on input coming from the user.

This illustrates the difference between compile-time and run-time: The compiler translates your code to machine code at compile-time, but user input is only available at run-time.

(My code examples are not perfect code. For example, I declare classes with virtual functions without declaring a virtual destructor. There are also other problems. This is only meant to illustrate the difference between compile-time and run-time, and show what is and what is not possible each time.)

Within any given function, at compile time, you can only deduce the things which will be true in any possible run of the function, regardless of the values of its input parameters. Whenever the data input to the function may change its behaviour, you cannot deduce the results in compile time.

Here, when we compile f, there is no way of knowing whether the object pointed to by a will be of type B or C, or some other derived type which we do not even know about (in this compilation unit). In fact, this can depend on user input and may vary from one run to another.

Thus, in compile time we do not know what function will actually be called when we type a->virt().

In runtime, however, we do know what a actually points to, and thus we can determine which function will be called.

In practice, virtual function calls are solved using a vtable, which is an array of pointers to all the virtual functions of the class.

I don't know what you currently think of as "compile time", but program compilation and linking both happen before the program is run and hence before the user provides the input. So the destination of the call to foo cannot possibly be determined at compile time, since it depends on user input at run time.

If foo were a non-virtual function then Base::foo() would be called regardless of the value of flag, so in that case the destination would be known at compile-time.

along with the above,in short
compile time is the time your source code is getting compiled,and run time is the time when your compiled code is getting executed,which may be dependent on your input to the program....,hence according to your input,it is decided at runtime that which object reference will be accessing the virtual function. here

At a bit more technical level (hope I have my facts straight :S), there is something called vtable which is built to achieve polymorphism.

Basically there can only be one vtable per class, so any instance of a class will share the same vtable, the vtable is invisible to the programmer so to speak, and it contains pointers to implementation of virtual functions.

It's the compiler that builds the vtables and they are only built if they are needed (i.e. if the class or it's base-class contains a virtual function. So worth noting is that not all classes get a vtable built.

example time:

class Base {
public:
virtual void helloWorld();
}
class Derived : public Base {
public:
void helloWorld();
}
int main(void) {
Derived d;
Base *b = &d;
b->helloWorld(); // here is the magic...
/* This call is actually translated to something like the line below,
lets assume we know that the virtual pointer pointing to the viable
for Derived is called Derived_vpointer (but it's only a name and
probably not what it would be called):
*(b -> Derived_vpointer -> helloWorld() )
*/

So, this mean that when b->helloWorld() is called it actually use a vpointer to look up a vtable which is substituted in to guide the call to the correct version of the virtual function. So the classDerived here, has a vtable and a virtual pointer pointing to the table. So when b is pointing to a Derived instance it will use the vpointer from Derived ending up calling the correct implementation.

This is done runtime or rather the lookup is done runtime because we could easily have another class extend Base and make b point to this (let us call it AnotherDerived) class. what happens when we again use b->helloWorld() is that the vpointer of AnotherDerived will be used to evaluate the call to helloWorld().