Understanding calling inherited methods from abstract class in C++ - 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.

Related

What are the use cases for a base class pointer pointing to a derived class object

I'm a new to OOP and trying to learn C++ and I came cross polymorphism and using the virtual keyword.
I just don't understand why we might need to do that.
I've checked this site for similar questions but none of them attempts to answer that why?
The main goal is: Separation of concerns.
Let's take an example from my day job. I work on a codebase that does networking. The vast majority of the codebase depends on a class that looks like:
class Transport
{
public:
virtual bool SendMessage(int clientId, string message);
};
Imagine I've got hundred files, and tens of thousand of lines of code, using this class.
Now, my colleague in the low-level team wants to allow our code to use both UDP and TCP for communications. They can simply implement:
class UdpTransport:public Transport
{
public:
bool SendMessage(int clientId, string message) override { /* their code */};
};
class TcpTransport:public Transport
{
public:
bool SendMessage(int clientId, string message) override { /* their code */};
};
This allows me to keep the whole of my code unchanged (using only Transport* or Transport&) and not have to worry about what a UdpTransport or TcpTransport is. It allows one part of the code to work without knowing what another part of the code is doing.
Most introductions of polymorphism start with something like this:
Base* b = new Derived(); // ouch :/
This is very unfortunate in my humble opinion, because it creates the misunderstanding that polymorphism implies manual memory managment via new. The topics are somewhat related. Though my example of polymorphism would start like this:
#include <iostream>
struct base {
virtual void say_hello() { std::cout << "hello base\n"; }
};
struct derived : base {
void say_hello() override { std::cout << "hello derived\n";}
};
void foo(base& b) {
b.say_hello();
}
int main()
{
base b;
derived d;
foo(b);
foo(d);
}
say_hello must be declared virtual to allow derived to override the method. If say_hello was not virtual then derived::say_hello would not override it.
If you remove virtual and override above you can see what happens when the method in the derived class does not override the method in the base class. The call b.say_hello() would then call base::say_hello() no matter if a base or derived is passed to foo because only for virtual methods the method to be called considers the dynamic type of the object.
What are the use cases for a base class pointer pointing to a derived class object
Same as the reference above. foo(base&) can take an object of any type that derives from base and then call its say_hello method. If this wasnt possible you would have to write a foo(derived), foo(derived2), foo(derived3) to call their say_hello method. In a nutshell, polymorphism means to treat different types the same. foo does not need to know what the dynamic type of its paramter is. It only needs to know that it inherites from base.
Many Design Patterns (GOF book) rely on virtual functions. The idea is that you have you work with an object of which you only know it's interface and when you call a function, what is done is based on the object that implements the interface.
One of the design patterns is Command where you have a container in which you can add command implementations and the handler of the container calls the "execute" function without having to worry about what the command actually is. The command implementation contains already the data it needs to run.
A common alternative for virtual functions is a switch case that needs to know all the implementations as an enum so the caller knows what to call exactly or an own implementation of a function-table.
Of course, if you don't see how such thing can improve your program, then it's best not to try and force it in.
Consider the following class architecture and function:
#include <iostream>
#include <string>
class Base
{
public:
std::string hello() const
{
return "Hello Base!";
}
};
class Derived : public Base
{
public:
std::string hello() const
{
return "Hello Derived!";
}
};
void outputHello(const Base& b)
{
std::cout << b.hello() << '\n';
}
We have:
A base class with a hello() method that returns "Hello Base!";
A derived class with a hello() method that returns "Hello Derived!";
A outputHello(const Base&) function that takes a reference to a Base object as its argument and prints out the result of a call to its hello() method.
Now, what do you think the following program will output?
int main()
{
Base b;
outputHello(b);
Derived d;
// Allowed as a reference/pointer to Base can
// reference/point to a Derived object
outputHello(d);
}
You probably guessed the following if you come from Java or a similar object-oriented language:
Hello Base!
Hello Derived!
But it instead it outputs Hello Base! twice. Why? It's actually quite simple. When the compiler gets to the outputHello function body it sees std:cout << b.hello() << '\n'. It thinks: Well, b is of type Base, so I'm gonna issue a call to Base::hello(). And it does exactly that, regardless of the type of the object we actually pass as argument to outputHello.
To solve this problem and get the output we expected, we need RTTI (Runtime Type Information), whose name speaks for itself. This is achieved by marking Base::hello() as virtual:
class Base
{
public:
virtual std::string hello() const
{
return "Hello Base!";
}
};
It is also good practice to mark Derived::hello() as override, though it is not necessary — override functions are automatically virtual.
class Derived : public Base
{
public:
std::string hello() const override
{
return "Hello Derived!";
}
};
We then get our expected output.

"One or more multiply defined symbols found". Static and friend function

I'm trying to use interface classes and I have the following class structure:
IBase.h:
#pragma once
class IBase
{
protected:
virtual ~IBase() = default;
public:
virtual void Delete() = 0;
IBase& operator=(const IBase&) = delete;
};
IQuackable.h:
#ifndef IQUACKABLE
#define IQUACKABLE
#include "IBase.h"
#include <iostream>
class IQuackable : public IBase
{
protected:
IQuackable() = default;
~IQuackable() = default;
public:
virtual void Quack() = 0;
static IQuackable* CreateInstance();
};
#endif //
MallardDuck.h:
#pragma once
#include "IQuackable.h"
class MallardDuck : public IQuackable
{
private:
MallardDuck();
protected:
~MallardDuck();
public:
void Delete() override;
void Quack() override;
friend IQuackable* IQuackable::CreateInstance();
};
MallardDuck.cpp:
#include "MallardDuck.h"
MallardDuck::MallardDuck() {}
MallardDuck::~MallardDuck() {}
void MallardDuck::Delete() { delete this; }
void MallardDuck::Quack()
{
std::cout << "Quack!\n";
}
IQuackable* IQuackable::CreateInstance()
{
return static_cast<IQuackable*>(new MallardDuck());
}
Also I've created class RedHeadDuck.h and .cpp with the same declaration and definition as MallardDuck.
And, finaly, main class code:
#include "MallardDuck.h"
#include "RedHeadDuck.h"
int main()
{
IQuackable* mallardDuck = MallardDuck::CreateInstance();
IQuackable* redHeadDuck = RedHeadDuck::CreateInstance();
mallardDuck->Quack();
redHeadDuck->Quack();
}
And here I got two errors:
LNK2005 "public: static class IQuackable * __cdecl IQuackable::CreateInstance(void)" (?CreateInstance#IQuackable##SAPAV1#XZ) already defined in MallardDuck.obj".
LNK1169 "one or more multiply defined symbols found".
As I find out, the problem is in double definition, but how it fix?
I've read about Header guards, but, as I understood, it can't help in this case. Also people write about inline functions, but I've not realized how it may be used here.
What can I do?
Goals
I suppose these are what you are trying to obtain by adopting all the complicated patterns:
interface, i.e., "multiple types, same set of methods"
some sort of abstract factory pattern, i.e., you want a "instantiator" who provides a static method (which is not very different from a global function) to call, and returns instances of derived classes
prohibit users from directly calling the ctors of derived classes
take care of the dtors by implementing the Delete() method
Requirement 1-3
There are at least 3 ways to meet requirement 1-3, as explained below:
1. Derived classes hiding static method of their base
This is the easiest way, and it's fully capable of current main.cpp. Derived classes can override static methods of their base class.
In file MallardDuck.h and RedHeadDuck.h:
// Replace this:
// friend IQuackable* IQuackable::CreateInstance();
// With this:
static IQuackable* CreateInstance();
In file MallardDuck.cpp (and RedHeadDuck.cpp similarly):
// Replace this:
// IQuackable* IQuackable::CreateInstance() {
// return static_cast<IQuackable*>(new MallardDuck());
// }
// With this:
IQuackable* MallardDuck::CreateInstance() {
return new MallardDuck();
}
The problem with this is that: other derived classes that don't override and hide CreateInstance() will still expose IQuackable::CreateInstance() as a "fallback". Thus:
if you don't actually implement IQuackable::CreateInstance() (so far, you don't have to), then once it is called via a derived class, the code won't compile and won't give a reason that's comprehensible to others; or
if you choose to implement it, you'd better throw an exception within it, which may surprise your user; otherwise you would have to return a nullptr or something, which is the worst practice in C++ (that's what we do in C since it has no language-level support for error handling; any C++ function that cannot fulfill its job should never return).
Either way is not elegant.
2. Adopt abstract factory pattern
This pattern requires a cooperating "factory class", which is abstract; then whenever you derive a concrete quackable, derive also its factory.
In your case you'll need to sketch out a IQuackableFactory, exposing IQuackableFactory::CreateInstance(), then derive a MallardDuckFactory and a RedHeadDuckFactory.
There are plenty of good examples already, so I won't demonstrate here.
3. Feature injection by using CRTP
There's yet another way of doing things. By CreateInstance() you're actually providing a "Give me an instance of this class!" feature. Typically we use the CRTP (curiously recurring template pattern) to "inject" a certain feature into a class.
First write this file EnableCreateInstance.hpp:
#ifndef _ENABLECREATEINSTANCE_HPP_
#define _ENABLECREATEINSTANCE_HPP_
template <class T>
struct EnableCreateInstance {
static T* CreateInstance() { return new T(); }
};
#endif //_ENABLECREATEINSTANCE_HPP_
Then in MallardDuck.h:
// Add:
#include "EnableCreateInstance.hpp"
class MallardDuck : public IQuackable, public EnableCreateInstance<MallardDuck> {
private:
MallardDuck();
friend class EnableCreateInstance<MallardDuck>;
...
In file RedHeadDuck.h do the similar: include header, publicly inherit EnableCreateInstance<RedHeadDuck>, and declare EnableCreateInstance<RedHeadDuck> as friend class.
This provides more flexibility: you're still providing an interface CreateInstance(), but in a less "aggressive" way: derived classes have their freedom to choose whether or not to provide CreateInstance(). If they do, just inherit and (if ctor made private) declare friendship; if not, omit the additional inheritance.
Requirement 4
Well, actually you can use delete this in non-static non-dtor method. But:
You must ensure (which can be difficult) that no more access to the deleted object's data members or virtual functions are made, otherwise it causes undefined behaviors;
You leave your users with dangling pointers to the deleted object.
So, we seldom provide such "deleters" in modern C++. You can get all the benefits it may provide through smart pointers, plus the ability to avoid UBs and so much more.

C++: compiling function call to unrelated derived class, bug or feature?

Fooling a bit around in C++, I stumbled across something which I believe is an error of both clang++ (6.0) and g++ (5.3): I am able to trick the compiler to call functions it should not be able to.
In short, I am declaring an abstract base class from which I derive two classes: a non-abstract and an abstract, which are related only via their common base class but have different functions. Instantiating the non-abstract base class and tricking the compiler to create a pointer of the abstract derived class pointing to the non-derived, I am able to call - via that pointer - a function of the original non-abstract class and the abstract class.
Minimal example, the two lines which give me a headache are at the bottom, separated by a comment line with stars:
#include <cassert>
#include <iostream>
#include <typeinfo>
class MYBase {
public:
virtual void fun1() = 0;
};
class MYDer1 : public MYBase {
public:
~MYDer1() { std::cout << "~MYDer1()\n"; }
void fun1() { std::cout << "MYDer1 fun1\n"; }
};
class MYDer2 : public MYBase {
public:
~MYDer2() { std::cout << "~MYDer2()\n"; }
void something2() { std::cout << "MYDer2 something2\n"; }
};
int main () {
MYDer1 x1;
// Good: cannot instantiate a 'MYDer2' as it is an abstract class
// due to unimplemented pure virtual method 'fun1' in 'MYDer2'
//
// MYDer2 x2;
// Good, clang++ and g++ rightfully refuse to compile this:
//
// auto * pd2 = static_cast<MYDer2 *>(&x1);
// So let's be 'clever' and take a detour via 'void':
auto * pd2 = static_cast<MYDer2 *>(static_cast<void *>(&x1));
// Just to be sure the compiler got it right
assert(typeid(pd2) == typeid(MYDer2 *));
/***********************************************************/
// There is no "fun1" declared in MYDer2
// So why does this even compile?
pd2->fun1();
// And why does this execute correctly?
pd2->something2();
return 0;
}
What am I missing?
It is undefined behavior so this time you shot yourself in the leg but missed. It is a programmer's responsibility to ensure that pointer being dereferenced really points to the object of specified type.
This is undefined behavior because x1 is of type MYDer1 and you cast it by force to MYDer2. The code might not work because you are not really doing anything with function something2. Try to add a member variable to MYDer2 and print it to see the problem.

c++ templates, virtual funcs, empty base

Still getting the hang of c++ classes, and I'm wondering what is the most run-time-efficient way to accomplish this:
I have a derived class that I want to instantiate once (known at compile-time), but I want to typecast the pointer to a base class pointer and pass that around for the rest of my program to use. That way, if I have a future project where I want to change the instance from animal.dog to animal.cat, all other parts of my code will still be able to call the method animalPtr->eat(), but the actual behavior will be specific to dog or cat. I will only ever have 1 instance of animal.dog or animal.cat, and I will never have an instance of base-class animal.
Maybe doing exactly what I just described is exactly how I need to do it, but I read some online arguments about the pros and cons of having the base class "animal" use virtual functions versus having the base class be a template class (not exactly sure how to even make it into a template in this case....to me, templates classes looked like they were used for creating generic data types for the members, but that is not what I'm needing here).
Any help? Remember that speed-performance is the highest priority for me.
Using a virtual function is the object oriented way to solve this. With the usual implementation of virtual functions, it adds another pointer indirection and makes inlining impossible so if you really, really, really have performance issues and the function is small and called millions of times in a tight loop, then you might have a performance issue.
Use the virtual function approach to start with. If it is a problem (and you have measured that this is indeed the problem with a profiler), then you can look into changing things to a template based approach that might be more efficient.
to implement what you want w/o virtual functions can be done by templating the base class:
template<class Parent>
class BASE {
public:
BASE();
virtual ~BASE();
void func() {
reinterpret_cast<Parent*>(this)->func(); // call parent func
// or
(Parent*)(this)->func();
}
};
You can later typedef the BASE class to a normal class name:
typedef BASE<specific_Parent> myBASE;
It seems to me you are trying to decide between run-time and compile-time polymorphisms. If you do really need run-time polymorphism you have to use virtual functions. But if you don't really need run-time polymorphism, you can use CRTP to achieve the compile-time polymorphism.
This is a very primitive example illustrating the compile-time polymorphism (code on ideone.com):
#include <iostream>
namespace so {
template<typename _t_derived_>
class _animal_ {
private:
using _derived_ = _t_derived_;
public:
void eat() const {
static_cast<_derived_ const *>(this)->eat_impl();
}
};
class _dog_: public _animal_<_dog_> {
friend class _animal_<_dog_> ;
private:
using _base_ = _animal_<_dog_>;
protected:
void eat_impl() const {
std::cout << "dog's eating." << std::endl;
}
};
class _cat_: public _animal_<_cat_> {
friend class _animal_<_cat_> ;
private:
using _base_ = _animal_<_cat_>;
protected:
void eat_impl() const {
std::cout << "cat's eating." << std::endl;
}
};
template<typename _t_animal_>
void feed(_t_animal_ const & _animal) {
std::cout << "feeding an animal: ";
_animal.eat();
}
} // namespace so
int main() {
so::_dog_ dog_;
so::_cat_ cat_;
so::feed(dog_);
so::feed(cat_);
return (0);
}
Program output:
feeding an animal: dog's eating.
feeding an animal: cat's eating.

What's the usage if I provide an implementation for a pure virtual function in C++

I know that it's OK for a pure virtual function to have an implementation. However, why it is like this? Is there conflict for the two concepts? What's the usage? Can any one offer any example?
In Effective C++, Scott Meyers gives the example that it is useful when you are reusing code through inheritance. He starts with this:
struct Airplane {
virtual void fly() {
// fly the plane
}
...
};
struct ModelA : Airplane { ... };
struct ModelB : Airplane { ... };
Now, ModelA and ModelB are flown the same way, and that's believed to be a common way to fly a plane, so the code is in the base class. However, not all planes are flown that way, and we intend planes to be polymorphic, so it's virtual.
Now we add ModelC, which must be flown differently, but we make a mistake:
struct ModelC : Airplane { ... (no fly function) };
Oops. ModelC is going to crash. Meyers would prefer the compiler to warn us of our mistake.
So, he makes fly pure virtual in Airplane with an implementation, and then in ModelA and ModelB, put:
void fly() { Airplane::fly(); }
Now unless we explictly state in our derived class that we want the default flying behaviour, we don't get it. So instead of just the documentation telling us all the things we need to check about our new model of plane, the compiler tells us too.
This does the job, but I think it's a bit weak. Ideally we instead have a BoringlyFlyable mixin containing the default implementation of fly, and reuse code that way, rather than putting code in a base class that assumes certain things about airplanes which are not requirements of airplanes. But that requires CRTP if the fly function actually does anything significant:
#include <iostream>
struct Wings {
void flap() { std::cout << "flapping\n"; }
};
struct Airplane {
Wings wings;
virtual void fly() = 0;
};
template <typename T>
struct BoringlyFlyable {
void fly() {
// planes fly by flapping their wings, right? Same as birds?
// (This code may need tweaking after consulting the domain expert)
static_cast<T*>(this)->wings.flap();
}
};
struct PlaneA : Airplane, BoringlyFlyable<PlaneA> {
void fly() { BoringlyFlyable<PlaneA>::fly(); }
};
int main() {
PlaneA p;
p.fly();
}
When PlaneA declares inheritance from BoringlyFlyable, it is asserting via interface that it is valid to fly it in the default way. Note that BoringlyFlyable could define pure virtual functions of its own: perhaps getWings would be a good abstraction. But since it's a template it doesn't have to.
I've a feeling that this pattern can replace all cases where you would have provided a pure virtual function with an implementation - the implementation can instead go in a mixin, which classes can inherit if they want it. But I can't immediately prove that (for instance if Airplane::fly uses private members then it requires considerable redesign to do it this way), and arguably CRTP is a bit high-powered for the beginner anyway. Also it's slightly more code that doesn't actually add functionality or type safety, it just makes explicit what is already implicit in Meyer's design, that some things can fly just by flapping their wings whereas others need to do other stuff instead. So my version is by no means a total shoo-in.
Was addressed in GotW #31. Summary:
There are three main reasons you might
do this. #1 is commonplace, #2 is
pretty rare, and #3 is a workaround
used occasionally by advanced
programmers working with weaker
compilers.
Most programmers should only ever use #1.
... Which is for pure virtual destructors.
There is no conflict with the two concepts, although they are rarely used together (as OO purists can't reconcile it, but that's beyond the scope of this question/answer).
The idea is that the pure virtual function is given an implementation while at the same time forcing subclasses to override that implementation. The subclasses may invoke the base class function to provide some default behavior. The base cannot be instantiated (it is "abstract") because the virtual function(s) is pure even though it may have an implementation.
Wikipedia sums this up pretty well:
Although pure virtual methods
typically have no implementation in
the class that declares them, pure
virtual methods in C++ are permitted
to contain an implementation in their
declaring class, providing fallback or
default behaviour that a derived class
can delegate to if appropriate.
Typically you don't need to provide base class implementations for pure virtuals. But there is one exception: pure virtual destructors. In fact if your base class has a pure virtual destructor, it must have an implementation. Why would you need a pure virtual destructor instead of just a virtual one? Typically, in order to make a base class abstract without requiring the implementation of any other method. For example, in a class where you might reasonably use the default implementation for any method, but you still don't want people to instantiate the base class, you can mark only the destructor as pure virtual.
EDIT:
Here's some code that illustrates a few ways to call the base implementation:
#include <iostream>
using namespace std;
class Base
{
public:
virtual void DoIt() = 0;
};
class Der : public Base
{
public:
void DoIt();
};
void Base::DoIt()
{
cout << "Base" << endl;
}
void Der::DoIt()
{
cout << "Der" << endl;
Base::DoIt();
}
int main()
{
Der d;
Base* b = &d;
d.DoIt();
b->DoIt(); // note that Der::DoIt is still called
b->Base::DoIt();
return 0;
}
That way you can provide a working implementation but still require the child class implementer to explicitely call that implementation.
Well, we have some great answers already.. I'm to slow at writing..
My thought would be for instance an init function that has try{} catch{}, meaning it shouldn't be placed in a constructor:
class A {
public:
virtual bool init() = 0 {
... // initiate stuff that couldn't be made in constructor
}
};
class B : public A{
public:
bool init(){
...
A::init();
}
};