Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Once a function name has been declared as 'virtual', can it ever be be made un-virtual again?

Tags:

c++

virtual

So let us say I have some chain of classes where each class is derived from the class before it. For whatever reason, they all like to use the same name for some member function. Kinda like this:

class C1 { public:             void f() { cout<<"C1"; }; };
class C2 : public C1 { public: void f() { cout<<"C2"; }; };
class C3 : public C2 { public: void f() { cout<<"C3"; }; };

Obviously, if I just declare some objects, then call the function f from them, all will call the function associated with their respective object-type:

C1 c1; c1.f(); // prints C1
C2 c2; c2.f(); // prints C2
C3 c3; c3.f(); // prints C3

Now, if I declare some pointers-to-objects, then call the function f from them, all will call the function associated with their respective pointer-type:

C1* p1 = &c1; p1->f(); // prints C1
C1* p2 = &c2; p2->f(); // prints C1
C1* p3 = &c3; p3->f(); // prints C1
C2* p4 = &c2; p4->f(); // prints C2
C2* p5 = &c3; p5->f(); // prints C2
C3* p6 = &c3; p6->f(); // prints C3

All of this is super. I either call the function associated with the object's type or I call the function associated with the pointer's type...

Or of course I could make the function 'virtual'. Then if I call the function from some object, I will get no change in behavior; however, if I call the function from some pointer, then I won't just call the function for the pointer's type, I will actually call the function for the object-type that the pointer is pointing to. So far so good.

I can even make the change to virtual mid-way through the chain of inheritance. Let's say I put a virtual before the function f inside of class C2. Now the function has been made virtual (i.e. when called from pointers, it uses the object-pointed-to-type instead of the pointer-type to resolve the function call), not only for its own class, but for all future classes that are derived from it.

My question is this: Once a function has been declared virtual (at some point in the chain of inheritance) can it ever be reverted back to being non-virtual (further down the chain of inheritance)?

For clarification: When I say revert back to non-virtual behavior, I mean that when I call the function from a pointer, it will use the pointer's type to resolve the function call (and not the object-type that the pointer is pointing to).

like image 600
Jimmy Avatar asked Sep 06 '25 12:09

Jimmy


1 Answers

Once a function has been declared virtual (at some point in the chain of inheritance) can it ever be reverted back to being non-virtual (further down the chain of inheritance)?

No. Once a function signature has been made virtual somewhere along the line of inheritance, it will stay that way: every function with the same signature in a derived class will be virtual as well.

One way to get around this is to use (abuse?) the template method pattern:

struct Base {
    virtual void doFoo() { bar(); }
    void foo() { doFoo(); }
};

struct Derived1 : public Base {
    virtual void doFoo() { baz(); }  // "overrides" foo via doFoo
};

struct Derived2 : public Base {
    void foo() { quux(); }  // "un-virtualize" foo by decoupling it from doFoo
};

In this inheritance tree, the pointer type will determine which foo is called; if it's the one from Base, the pointed-to object's type will determine which doFoo is called.

like image 77
Fred Foo Avatar answered Sep 09 '25 17:09

Fred Foo