0
votes

I am still trying to grip the concept of Abstract Base Classes and what can and cannot be done from the Derived class.

I have the following code :

class NpBaseTest {
    ...
    friend std::ostream& operator<<(std::ostream &os, const NpBaseTest& p_npBaseTest);
    /* Implemented in the .cpp file as -
    std::ostream& operator<<(std::ostream &os, const NpBaseTest& p_npBaseTest)
    {
        p_npBaseTest.show(os);
        return os;
    }
    */
    virtual uint16_t process(int) const = 0;

    virtual void show(std::ostream& os) const
    {
        os
            << "Test ID [" << get_test_id() << "] "
            << "Module Type [" << get_module_type() << "]" << std::endl;
    }
};

class CavTest : public NpBaseTest
{
    ...
    friend std::ostream& operator<<(std::ostream &os, const CavTest& p_cavtest);
    /* Implemented in the .cpp file as
    std::ostream& operator<<(std::ostream &os, const CavTest& p_cavtest) 
    {
        p_cavtest.show(os);
        return os;
    }
    */

    uint16_t process(int p_val) const
    {
        //...implemented here
    }

    void show(std::ostream& os) const
    {
        NpBaseTest::show(os);
        os
            << "CavTest Type" << std::endl;
    }
};

What I am hoping to do in the derived class show function, call the show function from the base class but I get the following error. What I understand is since NpBaseTest is an ABC it doesn't instantiate an object when the Derived class object is instantiated. So what are my options for achieving the desired functionality ?

Error message :

components/cavium/CavTest.cpp: In function 'void show(std::ostream&)': components/cavium/CavTest.cpp:20: error: cannot call member function 'virtual void NpBaseTest::show(std::ostream&) const' without object

UPDATE : Initial issue solved. Looking for more advice Is there a better way to call the base class function without having to specify the base class name with this->::show(os) ?

SOLUTION : I changed the base class show() routine to be a non virtual private member function which in turn calls a pure virtual show_all(ostream &os) function implemented by each derived class. That way I do no have to redefine the operator<< for every derived class and can avoid using <BaseClassName>::show()

Example in Base Class -

void NpBaseTest::show(std::ostream& os) const
{
    //Do base functionality here
    os
        << "Test ID [" << get_test_id() << "] "
        << "Module Type [" << get_module_type() << "]" << std::endl;

    // Call derived class routine here
    show_all(os); //This is declared as virtual void show_all(ostream& os) const = 0;
}

In Derived class

void CavTest::show_all(std::ostream& os) const
{
    os
        << "CavTest Type" << std::endl;
}
1
Please reduce your program to the smallest possible complete program that demonstrates the error. Please edit your question and copy-paste that entire short program into your question. Please copy-paste any error messages into your question. See minimal reproducible example for more info.Robᵩ
Try this->NpBaseTest::show(os);. But it should actually compile from what you're showing.πάντα ῥεῖ
@MooingDuck as I said, in the declaration, the class::function is not required as the implementation is already in the class declaration - I'm not referring to the function callUKMonkey
@ImNot Just out of curiosity: Which compiler are you using? As mentioned this-> should be implicit for an inherited virtual function override.πάντα ῥεῖ
Yes. This has caused confusion many times (with me, at least). I'm used to trust the indentation, but here on SO I should definitely not rely on that. Sigh.alain

1 Answers

0
votes

As shown your current problems have nothing to do with abstract (a.k.a. pure virtual) methods because there are none of those involved.

Problem 1: member function declaration syntax

The base class show() has an extra NpBaseTest:: qualifier that should not be there. You only need that extra qualifier when you define a member function outside the class declaration. The usual scenario for this:

// Foo.hpp
class Foo
{
    void bar();
}

// Foo.cpp
#include "Foo.hpp"
void Foo::bar()
{
    // ...
}

That’s the most likely reason for the error message you show.

Problem 2: visibility

The base class show() is private because in a class the default visibility is private. You cannot call private base class methods from a derived class, i.e. your call to NpBaseTest::show() – though syntactically correct – will not compile.

Problem 3: class declaration syntax

Both class declarations miss a ; after their closing brace.

The bare bones changes to get this to compile are:

class NpBaseTest
{
protected: // or: public:
    virtual void show(std::ostream& os) const { /*...*/ }
};

class CavTest : public NpBaseTest
{
    // private by default
    // Works because you can override with a lower visibility,
    // but not with a higher one.

    void show(std::ostream& os) const override
    {
        NpBaseTest::show(os);
        // ...
    }
};

override is optional but highly recommended if you use a C++11 capable (i.e. non-ancient) compiler.