简体   繁体   中英

C++ Inheritance and virtual keyword on base_class with derived class

Sorry maybe I should rewrite my question in a better way.

I've a base class name ABC that have function name.

void saysez(ostream &os) const // this is NOT virtual!!
            { os << sez; }

and derived class name DEF that also have function name

void saysez(ostream &os) const { os << extra << " ";
                         scary::saysez(os);

So as we can see from the above code both having same signature.

In my understanding if there is no virtual keyword specified it should use the base class function but in my walkthrough practice the output it turned out that it is using the derived's function.

So I'm wondering why it is used the derived's function over base's function?

Below is the call from int main

     w.saysez(cout);  cout << '\n';

w is the object from derived class.

Below is the link to the snipped code with an output

http://codepad.org/Pz5jwMVP

I have a hard time understanding your question. The virtual keyword seems irrelevant to this problem. Your class witch has a member function void saysez(ostream&) and when you create an instance of this class and call w.saysez, the compiler matches the definition of saysez it found in your implementation of witch.

The virtual keyword really doesn't matter here. If don't want to see the 'Double Double' part, then cast w to a scary:

((scary*)&w)->saysez(cout)

and you won't see the 'Double Double' part printed out.

Please see this or just about any other site that discusses the virtual keyword for more information.

Here's a smaller sample you could have posted that still demonstrates your issue:

#include <iostream>
using namespace std;
#include <cstring>

class scary {
    char is[31];
    char sez[31];
public:
    scary() {
        strcpy(is, "Creep");
        strcpy(sez, "boooo");
    }
    scary(const char i[], const char s[])
    {
        strcpy(is, i); strcpy(sez, s);
    }
    virtual void sayis(ostream &os) const { os << is; }
    void saysez(ostream &os) const // this is NOT virtual!!
        { os << sez; }
};

ostream &operator<<(ostream &os, const scary &x) {
    x.saysez(os);
    os << ", said the ";
    x.sayis(os);
    return os;
}

class ghost: public scary {
public:
    ghost():scary("Ghost", "Boo!")
    {
    }
};

class witch: public scary {
    char extra[31];
public:
    witch(): scary("Witch", "Toil and Trouble") {
        strcpy(extra, "Double, Double");
    }
    void saysez(ostream &os) const {
        os << extra << " ";
        scary::saysez(os);
    }
};

int main() {
    scary s; 
    ghost g; 
    witch w;
    cout << s << '\n' << g << '\n' << w << '\n';
    return 0;
}

Output:

boooo, said the Creep
Boo!, said the Ghost
Toil and Trouble, said the Witch

In witch 's constructor, you set the sez array to "Toil and Trouble" and then in saysez declared in witch you print out extra and call scary 's saysez function which prints out sez . This happens because it is possible (but not encouraged) to override non-virtual member functions .

I am guessing that w is declared as an element of type witch, so of course it is going to call witch::saysez(). If, though, you did:

scary* w2 = new witch();
w2->saysez(cout);

...then you should see the scary::saysez() behavior.

It looks like you have misunderstood how non-virtual functions work with inherited classes. Both virtual and non-virtual functions can be overridden. On an object of class Foo, if you call Foo::MyNonVirtualFn(), it will just execute the body of Foo::MyNonVirtualFn(). If Foo has a superclass that implements MyNonVirtualFn(), or if the object it's being called on is actually an instance of a subclass of Foo that overrides MyNonVirtualFn() -- none of that matters. If the function call is to Foo::MyNonVirtualFn(), then that is the version of the function that runs. (If you aren't explicit about what version of MyNonVirtualFn() you're calling it infers it from the type that you're calling it with -- for pointer or reference types this might not be exactly the same as the type of the object.)

Virtual functions are different in that if you call Foo::MyVirtualFn() on an object it will check to see if the object is an instance of a subclass of Foo that has overridden MyVirtualFn() . So, for instance:

Base* base = new Base();
Derived* derived = new Derived();
Base* derived_as_base = derived;

base->MyNonVirtualFn();  // Calls Base::MyNonVirtualFn().
derived->MyNonVirtualFn();  // Calls Derived::MyNonVirtualFn().
derived_as_base->MyNonVirtualFn();  // Calls Base::MyNonVirtualFn() because it's called on a Base*.

base->MyVirtualFn();  // Calls Base::MyNonVirtualFn().
derived->MyVirtualFn();  // Calls Derived::MyNonVirtualFn().
derived_as_base->MyVirtualFn();  // Calls Derived::MyNonVirtualFn() because it uses a lookup table.

Firstly, please correct me if I don't understand your question correctly.

We use inheritance for many reasons and one of them is to code efficiently. For example, in your case,

you want to inherit the class scary which means you want to have the functionality of class scary in the derived classes. You can copy all of the member functions in the based class to have the same functionality as the based calls, but what if you decide to change something in one of the functions? you have to change all of them. so it is inefficient way of coding.

Now in you class, you asking why is object w in this line w.saysez(cout); cout << '\\n'; w.saysez(cout); cout << '\\n'; because both class scary and class which have the same member function, the w should look in its class first for a match, if it doesn't find it, it will then look in the based class. Therefore, your object is calling the saysez member function in its class.

hope this will help.

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