Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ classes: virtual and override, or neither?

Is it actually necessary to use either virtual or override?

I'm aware that there are a lot of questions on this general topic, e.g.:

  • C++ “virtual” keyword for functions in derived classes. Is it necessary?
  • Is the 'override' keyword just a check for a overridden virtual method?
  • virtual? override? or both? C++

From those, and others marked as duplicates (the answers to a lot of the "duplicates" have contained distinct information that was new at least to me), I've learned some things (and, I think, roughly why they're true): override without virtual will not compile. Virtual without override will compile, but if you've made a mistake and don't have your method signature correct, the compiler won't tell you.

But what's going on if I omit both? Example:

struct BaseClass {
    int a_number() {
        return 1;
    }
};
struct DerivedClass : BaseClass {
    int a_number() {
        return 2;
    }
};

This compiles, and a_number returns the appropriate result whether I instantiate BaseClass or DerivedClass. So it behaves as though I have overridden the function. Is there some reason why the code above is wrong? Is it a backwards-compatibility issue, or something more?

My apologies if this is answered directly in one of the related questions here that I missed, and thanks.

EDIT: StackOverflow keeps pointing me to the C++ “virtual” keyword for functions in derived classes. Is it necessary? question, as Wyck did below. I do not think it addresses my question, for the reason I gave him/her in the comments, which, since they are transitory, I'll repeat here: "I'm specifically asking about virtual in superclass methods, while that post seems to be about virtual in subclasses and how it propagates. The accepted answer below answers my question, but I don't think your link does (it might answer the question for someone more experienced in C/C++, but I don't think it answers it for a novice coming from Python and Java, like me)."

The point: I think the questions are related, but not the same.

I've accepted selbie's answer, since it was the first full-fledged "Answer" that answered my question. Wyck's answer provided a lot of useful, more general information.

like image 713
TCF Avatar asked Jan 17 '26 08:01

TCF


1 Answers

As you have it declared (no virtual methods), Without BaseClass::a_number being declared virtual, an instance of DerivedClass when casted back as BaseClass will not invoke the implementation in the DerivedClass

Example:

BaseClass* instance1 = new DerivedClass();
instance1->a_number();  // returns "1", even though the object is really an instance of Derived

If BaseClass had been declared as follows:

struct BaseClass {
    virtual int a_number() {
        return 1;
    }
};

Then the following code works as you might expect

BaseClass* instance2 = new DerivedClass();
instance2->a_number();  // returns "2", virtual method invocation

The override keyword is optional, but recommended in DerivedClass:

struct DerivedClass : BaseClass {
    int a_number() override {
        return 2;
    }
};

As you have already observed, override doesn't change the program behavior, but if a_number hadn't been declared identically in BaseClass, the compiler will issue an error. It's useful for catching typo errors.

like image 128
selbie Avatar answered Jan 20 '26 02:01

selbie



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!