0

If we create an object pointer to base class class which points to its child class object then we use virtual key word for late binding So.,in case of late binding,, our code goes like this :-

#include<iostream>
using namespace std;
struct A{
    virtual void print() {
        cout<<"function1";
    }
};

struct B : public A{
    void print(){
        cout<<"function2";
    } 
};

struct C : public B{
    void print(){
        cout<<"function3";
    } 
};

int main(){
    A* a = new C();
    A* p = new B();
    a->print();
    p->print();
} 

Now my question is : when we use virtual keyword in base class, all the functions of derived classes created in base class will become virtual. In multilevel inheritance, is there any way so that we can stop the function of class c from being virtual?? Any way to break this chain of virtual functions ? Sorry for any mistakes in question but i tried my best.. ☺️☺️

AndyG
  • 39,700
  • 8
  • 109
  • 143
GeekyCoder
  • 138
  • 11
  • from `C::print()` you can call `B::print()` does that help? – RyanP Jun 05 '17 at 13:14
  • 3
    This sounds like an [XY problem](http://xyproblem.info/). What's the real issue you're trying to solve? – G.M. Jun 05 '17 at 13:21
  • Possible duplicate of [How to define sealed class in C++?](https://stackoverflow.com/questions/4712992/how-to-define-sealed-class-in-c) – default Jun 05 '17 at 13:23
  • 1
    @Default That's not a duplicate, the OP appears to want to still be able to inherit the class, but prevent the methods from being overridden. The answer to the question you link to prevents inheritance entirely. – Pharap Jun 05 '17 at 13:25
  • 1
    Funny that you say it's not a duplicate, @Pharap, since the accepted answer to that question is almost exactly the same as your answer to this question. (Except that yours assumes C++11; Nawaz's doesn't.) – Cody Gray - on strike Jun 05 '17 at 13:27
  • I agree with G.M., it sounds like this is a symptom of your problem and not the root cause. Telling us why you want to do this might help us provide a better solution to your actual problem rather than just answering your current potentially misguided question. – Pharap Jun 05 '17 at 13:28
  • 1
    Are you perhaps looking for [final](http://en.cppreference.com/w/cpp/language/final) ? – Jesper Juhl Jun 05 '17 at 13:29
  • @CodyGray The two answers are talking about different uses of the final specialiser with different behaviour. The answer you linked to is discussing the unwanted behaviour of completely preventing inheritance of the class. What the OP asked for was the ability to prevent the virtual functions from 'being virtual' (i.e. being overridden), which is what the other behaviour of final is. One keyword, two different behaviours. – Pharap Jun 05 '17 at 13:30
  • There seems to be some ambiguity in this question, what exactly do you mean by "stop the function of class c from being virtual"? I asssumed that you meant you do not want the function to be allowed to be overridden, but perhaps you meant something else. – Pharap Jun 05 '17 at 13:34
  • I dont want it to be overridden... @Pharap – GeekyCoder Jun 05 '17 at 17:20

1 Answers1

1

It is not possible to make a function that is already virtual be not virtual in a child class.

Virtuality is a property of the top-level base class, not the child classes. Once a method has been marked as virtual, and pointer to that class must use dynamic dispatch for that function when calling because the pointer could be pointing to a child class that has overridden the behaviour.

Consider this code:

A a;
B b;
C c;

A * ap = &a;
A * bp = &b;
A * cp = &c;

ap->print(); // 'function1'
bp->print(); // 'function2'
cp->print(); // 'function3'

Here, the calls to print cannot tell which function to call at compile time, they absolutely must use dynamic dispatch.

However, you can make C::print behave like A::print

struct C : public B {
    void print() {
        A::print();
    }
};

Which results in:

ap->print(); // 'function1'
bp->print(); // 'function2'
cp->print(); // 'function1'

And if the behaviour of A::print() changes, C::print() mirrors those changes.

This will still be overridable though, unless you use the final keyword as outlined below.


Original answer:

I believe you are looking for the final specifier. It's only available as of C++11 though.

To quote en.cppreference's page about the final specifier:

When used in a virtual function declaration or definition, final ensures that the function is virtual and specifies that it may not be overridden by derived classes. The program is ill-formed (a compile-time error is generated) otherwise.

And a variation of the example they give, demonstrating the solution to your problem:

struct A
{
    virtual void foo();
};

struct B : A
{
    void foo() final; // B::foo is overridden and it is the final override
};

struct C : B
{
    void foo() override; // Error: foo cannot be overridden as it's final in B
};
Pharap
  • 3,826
  • 5
  • 37
  • 51
  • 1
    `final` is only making it illegal to define a function. What OP wants is to still be able to make `B::foo` but have it not be virtual. – AndyG Jun 05 '17 at 13:23
  • 1
    `final` will allow the compiler to de-virtualize calls to `foo()` in many cases. This is the best you can do. It's not possible to make a virtual function non-virtual in a derived class. – Peter Ruderman Jun 05 '17 at 13:25
  • @AndyG The exact question was "is there any way so that we can stop the function of class c from being virtual?" and that is exactly what the final specialiser does. The OP did not ask 'how can we access the parent's definition of foo?'. – Pharap Jun 05 '17 at 13:27
  • 1
    @Pharap: The final specifier doesn't make the function non-virtual if you try to define it, it just makes it illegal for another derived class to override it. Check out the [error message here](https://wandbox.org/permlink/nZfnmRfrsmxNmX4a): "error: virtual function 'virtual void C::print()'" – AndyG Jun 05 '17 at 13:29
  • @AndyG I assumed by 'non-vritual' the OP meant 'cannot be overridden'. The question is ambiguous, all we can do is wait for clarification as to what the OP's intended meaning was. – Pharap Jun 05 '17 at 13:32
  • @Pharap yes, i meant "cant not be overridden"... You are getting it correctly... But using final keyword is only generating an error message that it cant be overridden. – GeekyCoder Jun 05 '17 at 15:03
  • @SankalpSoni What behaviour are you expecting? When you write `C c = C(); A* a = &c; a.print()`, what do you expect to be printed? "function 2"? And when you do `C c = C(); c.print();` you expect "function 3" or "function2"? – Pharap Jun 05 '17 at 17:17
  • If it was early binding then the called functions should print the output of the function declared in base class which is "function1".... I meant it should print function1 if we make it non-virtual which is early binding again.... I dont know if it is possible – GeekyCoder Jun 05 '17 at 17:26
  • That's not possible. You can't call a function virtual and then make it not virtual later. If you made it not-virtual then B wouldn't be able to override it. You can however make `C::print` behave like `A::print`, but you have to do it manually. The function will still be virtual however. See my edited answer. – Pharap Jun 05 '17 at 18:40