C++: Learning About Virtual Classes

Over the weekend, I was given something to learn for a potential job (in Sverige) and that was Virtual Classes in C++. If you’re familiar with Partial Classes the idea kind of related, only it’s better. I’m sure how much of a pain it will be to debug but that’s the next thing that I want to test.

Anyways, Virtual Classes work off of inheritence and just like inheritence, you’re “wrapping” one object around another but with virtual classes, the exposure is seemless.

Take these two classes for a principle example:

#include iostream
#include cstring // Replacing the old and busted with the new hotness.

class LabEquipment
{
    public:
        explicit LabEquipment(int number)
        {
            std::cout << "Lab Equipment: " << number << "\n";
        }

        virtual void LabWrite(std::string message)
        {
            std::cout << "Writing " << message << " from LabEquipment.\n";
        }
};

class Tubes : virtual public LabEquipment
{
    public:
        Tubes(int tubes, int number)
                : LabEquipment(number)
        {
            std::cout << "Tubes: " << tubes << "\n";
        }

        virtual void TubesWrite(std::string tubesMessage)
        {
            std::cout << "Writing " << tubesMessage.c_str() << " from Tubes.\n";
        }
};

I can then write the following to leverage both Tubes and LabEquipments classes:

// Object
Tubes tubes(2, 3);
tubes.TubesWrite("hello");
tubes.LabWrite("hello, again, ");

// Pointer
Tubes * pTubes = new Tubes(3,4);
pTubes->TubesWrite("hello");
pTubes->LabWrite("hello, again,");

If I debug this in CLion (on Ubuntu 18.04LTS), then I get what I would expect:

Lab Equipment: 3
Tubes: 2
Writing hello from Tubes.
Writing hello, again,  from LabEquipment.
Lab Equipment: 4
Tubes: 3
Writing hello from Tubes.
Writing hello, again, from LabEquipment.

Note that I didn’t have to do anything else but declare the class’ inheritence for the methods to be exposed. None of that this stuff is necessary for it for it to be exposed, as it’s purely abstracted from the child to the parent.

In this way, C++ affords more versatility that .NET, in that, if I truly need to change any part of a class, there needn’t be any further changes – save on the caller.

Now, suppose that I declare the same method twice:

class ShowMessage
{
    public:
        explicit ShowMessage{};
    
        void virtual OutMessage(std::string message)
        {
            std::cout << "Writing " << message << " from WriteMessage.";
        }
};

class DisplayMessage : virtual public ShowMessage
{
    public:
        DisplayMessage()
                : ShowMessage()
        {};
        
        void OutMessage(std::string message)
        {
            std::cout << "Writing " << message << " from DisplayMessage";
        }
};

Our compiler, if it’s anything worwhile, should immediately alert us that we hiding the method; which, in this case, happens.

Markering_027

The IDE telling us that we’ve errored and suggesting ways to fix it.

If we override the method we can just drive on, as if nothing ever happened. We can also delete the method in DisplayMessage (which is what we should really do, as it’s redundant code already accomplished from within the ShowMessage class).

Now, let’s suppose we look at properties. Here’s a basic set of classes with int properties:

class FirstCount
{
    public:
        int Forsta;

    public:
        explicit FirstCount(int count)
        {
            Forsta = count;
        };
};

class SecondCount : virtual public FirstCount
{
    public:
        int Andra;

    public:
        SecondCount(int secondCount, int firstCount)
                : FirstCount(firstCount)
        {
            Andra = secondCount + Forsta;
        };
};

We can then construct an object that references them.

SecondCount secondCount(240, 547);
int first = secondCount.Forsta;
int second = secondCount.Andra;

When we debug, we can see that the value is what we’d expect (without having to have had used this).

Markering_028

You can see that the vlaue for second/Andra is the sum of 240 and 547, the 547 having been passed through from the FirstCount class.

…And that’s about as far as I’ve gotten, really… There’s a whole diamond thing that we could get into but I can’t be arsed to get that complicated with it, yet.

Anyways, thanks for coming to this NERDTalk and happy programming!