简体   繁体   中英

C++ virtual function: Base class function is called instead of derived

I have following code snippet:

class base
{
public:
    virtual void print(char a){ std::cout << " Base\n"; }
};

class derived : public base
{
public:
    void print(float a)  { std::cout << " Derived\n"; }
};

int main() {
    base* d = new derived;
    d->print(1.5);
}

Output is Base .

Why is the output coming from the base function and not from the derived one?

When you declare Base* d = new Derived; , the type of the class is Base, as printed by typeid(d).name() , so this instance doesn't have access to child class methods. If you change the type to Derived, you'll call the child method:

#include <iostream>
#include <typeinfo>

class Base
{
  public:
    virtual void print(char a) {
        std::cout << " Base " << std::endl;
    }
};

class Derived : public Base
{
  public:
    void print(float a) {
        std::cout << " Derived " << std::endl;
    }
};

int main()
{
    Derived* d = new Derived;
    std::cout << "class type is: " << typeid(d).name() << std::endl;
    d->print(1.5);

    return 0;
}

Output:

class type is: P7Derived
 Derived 

Furthermore, declaring the parent class print method virtual doesn't allow an instance of Base to call the child version of print because the child hasn't overridden it (different headers). Creating an instance of Base with Base *d = new Derived; and changing the Derived print method header to void print(char a) in the Derived class would allow you to call the child print method and output Derived , even from an instance of Base, using the virtual keyword.

#include <iostream>
#include <typeinfo>

class Base
{
  public:
    virtual void print(char a) {
        std::cout << " Base " << std::endl;
    }
};

class Derived : public Base
{
  public:
    void print(char a) {
        std::cout << " Derived " << std::endl;
    }
};

int main()
{
    Base* d = new Derived;
    std::cout << "class type is: " << typeid(d).name() << std::endl;
        d->print(1.5);

    return 0;
}

Output:

class type is: P4Base
 Derived

You have not overridden the function in the base class, you have overloaded it: The version in the derived class takes a float as an argument, and is quite a different beast from the base class method which takes a char . Moreover, the float version in the derived class shadows the base class version: The base class version becomes inaccessible for calls on the derived type.

As such, the following code

Derived d;
d.print('a');
d.print(1.5);

will print

Derived
Derived

because the call is resolved by the compiler to the only version of print() that's available in Derived .

Likewise, when you call d->print(1.5) through a pointer to Base , the derived class' version is inaccessible to the call: The compiler looks at the base class, sees that there is no print() method defined with a float argument, and converts the argument to char instead. It then calls the only implementation of print(char) , which happens to be supplied by the base class.


If you simply change the signature of the print() method in the derived class to match that of the base class, the odd behavior will go away.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM