-1

Given the codes below:

class Base
{
public:    
    virtual void f()
    {
        std::cout << "virtual Base::f()\n";
    }
};

class D1 : public Base
{
public:
    virtual void f()
    {
        std::cout << "virtual D1::f()\n";
    }
};

int main()
{
    D1 d1;
    Base *bp = &d1;
    bp->f();
    return 0;
}

The output was exactly what I had expected:

virtual D1::f()
Press <RETURN> to close this window...

But once I removed the virtual void f() from class Base, the compiler complained that:

error: 'class Base' has no member named 'f'

Can anyone tell me why compiler didn't generate codes such that it can bind virtual functions at rum time?

Yue Wang
  • 1,710
  • 3
  • 18
  • 43

3 Answers3

2

You are calling virtual member functions via a pointer to Base. That means that you can only call methods that exist in the Base class. You cannot simply add methods to a type dynamically.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • So..do you mean that it is not allowed to dynamically call any virtual function declared and defined within derived classes but not declared within base class? – Yue Wang Jan 23 '14 at 22:49
  • 1
    @Alan.W Right, not through a base class pointer anyway. You can try casting to the derived type, then calling the derived functions. – juanchopanza Jan 23 '14 at 22:50
1

Although a little late as an answer, straight quote from C++ Primer on how function calls are resolved in relation to inheritance. Your code fails on name lookup (step 2 below), which is done statically.

Understanding how function calls are resolved is crucial to understanding inheritance in C++. Given the call p->mem() (or obj.mem()), the following four steps happen:

  1. First determine the static type of p (or obj). Because we’re calling a member, that type must be a class type.

  2. Look for mem in the class that corresponds to the static type of p (or obj). If mem is not found, look in the direct base class and continue up the chain of classes until mem is found or the last class is searched. If mem is not found in the class or its enclosing base classes, then the call will not compile.

  3. Once mem is found, do normal type checking (§6.1, p. 203) to see if this call is legal given the definition that was found.

  4. Assuming the call is legal, the compiler generates code, which varies depending on whether the call is virtual or not:

    – If mem is virtual and the call is made through a reference or pointer, then the compiler generates code to determine at run time which version to run based on the dynamic type of the object.

    – Otherwise, if the function is nonvirtual, or if the call is on an object (not a reference or pointer), the compiler generates a normal function call.

fllprbt
  • 103
  • 1
  • 10
0

Just use this main function:

int main()
{
    D1 d1;
    D1 *bp = &d1;
    bp->f();
    return 0;
}

This is because if the bp is a Base poiter, Name lookup will start from the class Base