简体   繁体   中英

Understanding calling inherited methods from abstract class in C++

I was doing an experiment on inheritance and abstract classes without using pointers (avoiding the use of new when possible), and I came across a behavior that makes sense but I havent found documentation on it on the internet (neither a name for it or example).
I create a class, Abstract that has two methods, one is defined and the other is not. Then, a class Inherited inherits from Abstract and implements this second method.
Heres the classes:
Abstract.hpp:

#ifndef ABSTRACT_HPP
# define ABSTRACT_HPP
#include <iostream>

class Abstract {
   public:
   Abstract() {};
   ~Abstract() {};

   virtual void DoSomethingAbstract() = 0;
   void DoSomethingNormal() {
       std::cout << "Inside Abstract::DoSomethingNormal" << std::endl;
       DoSomethingAbstract();
   }
};
#endif /* ABSTRACT_HPP */

Inherited.hpp:

#ifndef Inherited_HPP
# define Inherited_HPP

#include "Abstract.hpp"

class Inherited : public Abstract {
    public:
    Inherited() {};
    ~Inherited() {};

    virtual void DoSomethingAbstract() {
        std::cout << "Inside Inherited::DoSomethingAbstract" << std::endl;
    }
};

#endif /* Inherited_HPP */

The following main works as expected (the only implementation of each function is the one that is called):

#include "Abstract.hpp"
#include "Inherited.hpp"

int main() {

    Inherited a;

    a.DoSomethingNormal();
    return 0;
}

output:

Inside Abstract::DoSomethingNormal
Inside Inherited::DoSomethingAbstract

Mostly I'd like to know if this is a UB and I'm just getting lucky, an unfrequent way of checking runtime polymorphism (which should not since there are no pointers to abstract classes here), or a perfectly defined behaviour somewhere in the standard.
PS: I am compiling with g++ 9.4.0, with flags `-std=c++98 -Wno-c++0x-compat.

Your example seems simple -- and for the most part, it is. But it leads to some important concepts. First, what you can do is a google on c++ polymorphism . There are a lot of hits, and the first several didn't seem to be wrong.

Let's look at some of your code:

 virtual void DoSomethingAbstract() = 0;

This is referred to as a pure virtual function. It means you won't actually make this method, but you're going to reserve a slot for it (and can call it). It means you can not make instances of this class -- it's abstract. If you try to make one, the compiler will complain. Your subclasses MUST provide implementations or they are also abstract and can't be instantiated.

void DoSomethingNormal() { std::cout << "Inside Abstract::DoSomethingNormal" << std::endl; DoSomethingAbstract(); }

This method is NOT virtual. Your subclass can make its own copy of this method, but then you can get weird results. Let's say you do this: class Inherited: public Abstract { public: void DoSomethingNormal() {...} };

 void blah(Abstract &obj) {
     obj.DoSomethingNormal();
 }

It won't matter whether you pass in an Abstract or an Inherited -- because you didn't declare the method virtual, and because blah() doesn't know what you're passing in but thinks it's an Abstract, you'll get Abstract's version of DoSomethingNormal() .

But if you declare the method virtual, you're saying, "Use whichever version corresponds to the class that actually was instantiated."

This is polymorphism at it's most useful, important role.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM