Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does the nested class with override work?

Tags:

c++

I was wondering how can one explain this mechanism:

class Base{
  class Other;
  virtual void test() = 0;
};
class Other: Base{
  virtual void test() override;
};
void Other::test(){ /*do something*/}

It looks like I have a base class called Base. It contains of a nested class which inherits from the Base. So if I call:

Base obj;
obj.test(); <-- it trigers the test() function from the Other class, doesn't it?

What is the difference between the given example and the following:

class Base{
  virtual void test() = 0;
};
class Other: Base{
  virtual void test() override;
};
void Other::test(){ /*do something*/}

what would be the benefit of hidding the Other class in the Base class?

like image 422
user Avatar asked Mar 24 '26 21:03

user


2 Answers

class Base{
  virtual void test() = 0;
};
Base obj;  // #0

#0 is ill-formed as Base is an abstract class, as it has at least one pure abstract member function.

Abstract class

Defines an abstract type which cannot be instantiated, but can be used as a base class.

A pure virtual function is a virtual function whose declarator has the following syntax:

declarator virt-specifier(optional) = 0   

[...] An abstract class is a class that either defines or inherits at least one function for which the final overrider is pure virtual.

Dynamic dispatch on polymorphic objects happens when you are dispatching to a virtual function from a base pointer or reference, which (for the specific runtime call) references a derived object.

In the following example:

struct Base {
    virtual void test() const = 0;
};

struct A final : public Base {
    void test() const override {}; // #1   
};

struct B final : public Base {
    void test() const override {}; // #2   
};

void f(Base const& b) { 
    b.test();  // #3
}

the call to the virtual member function test() at #3 can dispatch to either A::test() or B::test(), depending on the argument to the function f.

f(A{});  // 'test()' call in 'f' dispatches to #1
f(B{});  // 'test()' call in 'f' dispatches to #2

what would be the benefit of hidding the Other class in the Base class?

In your original example, the Base class declares a nested class (but does not define it) to itself, meaning the Other class declared in Base is not the same as the Other class that derives from it.

  • Declaring nested classes within a class is a separate topic entirely orthogonal to class inheritance hierarchies
  • A forward declaration outside of a base class that intends to forward declare a derived class that the base class thinks may derive from it would be an anti-pattern, as the whole point with abstract (interface) classes is to provide a public client API that can be used polymorphically by different derived classes. In other words, a base class should generally never (need to) know about its derived classes (save for the special case of static polymorphism via the curiously recurring template pattern).
like image 128
dfrib Avatar answered Mar 27 '26 11:03

dfrib


The declaration of class Base::Other at line 2 in your first code example, has nothing to do with the declaration of class Other in line 5 of your first code example.

That is, the forward declaration of Base::Other does not match class Other.

There is benefit in having nested classes (for example, some implementations of the pimpl idiom do that), but to define the nested class, you would have to define it with:

class Base::Other {...}; // explicit specification of Base here
like image 42
utnapistim Avatar answered Mar 27 '26 09:03

utnapistim



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!