Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

redefine a non-virtual function in C++

Tags:

c++

When I read Effective C++, it says, never redefine a non-virtual function in C++.

However, when I tested it, the code below compiles correctly. So what's the point? It's a mistake or just a bad practice?

class A {

    public:
    void f() { cout<<"a.f()"<<endl;};   
};

class B: public A {
    public:
    void f() { cout<<"b.f()"<<endl;};   
};


int main(){

    B *b = new B();
    b->f(); 
    return 0;
}
like image 729
skydoor Avatar asked Jan 23 '10 21:01

skydoor


People also ask

What is virtual function in C++?

Virtual Function in C++ Difficulty Level : Medium Last Updated : 29 Jan, 2021 A virtual function is a member function which is declared within a base class and is re-defined (Overriden) by a derived class.

What happens when a class contains a virtual function?

As discussed here, If a class contains a virtual function then compiler itself does two things: If object of that class is created then a virtual pointer (VPTR) is inserted as a data member of the class to point to VTABLE of that class. For each new object created, a new virtual pointer is inserted as a data member of that class.

Can a virtual function be a static function?

Virtual functions cannot be static. A virtual function can be a friend function of another class. Virtual functions should be accessed using pointer or reference of base class type to achieve run time polymorphism.

Is it mandatory for derived class to override a virtual function?

It is not mandatory for derived class to override (or re-define the virtual function), in that case base class version of function is used. A class may have virtual destructor but it cannot have a virtual constructor.


3 Answers

Redefining a non-virtual function is fine so long as you aren't depending on virtual dispatch behavior.

The author of the book is afraid that you will pass your B* to a function that takes an A* and then be upset when the the result is a call to the base method, not the derived method.

like image 75
bmargulies Avatar answered Nov 15 '22 21:11

bmargulies


Try this:

int main(){
    A *b = new B();
    b->f(); 
    return 0;
}

I think the answer will be obvious once you see the result ;-).

Without being virtual, the late-binding mechanism will not be used, hence the function that is defined for that pointer type will be used, not late-binded function that you want to call. This leads to tons of badly trackable bugs.

Hence, what you are doing is creating a new function. It may be what you intended, but someone reading your code afterwards might expect the above code to work with late-binding. Very confusing.

One of the features I really wanted to see is a warning in such a case, with a "redefine" keyword to prevent it, but dreams are dreams, and reality is reality -_-

like image 21
Kornel Kisielewicz Avatar answered Nov 15 '22 22:11

Kornel Kisielewicz


The point is that if you, for instance, have a list of pointers to the base class (List<A *> list) and then call f(), the re-implemented method in B will not be called.

like image 42
Kyle Lutz Avatar answered Nov 15 '22 22:11

Kyle Lutz