Search code examples
c++overridingabstract-classvirtual-functions

Error: Object of abstract class type is not allowed


I am trying to override a function in a class that generates a header for my log file. To add to the header that the function generates I have to override it and am having difficulty doing so. Thanks to Niko's input below I edited my question below. I know now I cannot create an object from an abstract class, so I need to use a reference or pointer.

main.cpp

#include "log_headerbase.h"
#include "log_header.h"
main()
{
    logfile::headerBase *Obj = new logfile::header;
    Obj.log_header() >> "Add this text to my log file";
...
}

I get this error when I try to allocate memory to my pointer to my Obj. "Error: object of abstract class type "logfile::header" is not allowed."

log_header.h

#ifndef log_header_h
#define log_header_h

#include "log_headerbase.h"

namespace logfile
{
    class headerDerived : public headerBase
    {
    };
}
#endif

log_headerbase.h

#ifndef log_headerbase_h
#define log_headerbase_h

namespace logfile
{
    class headerBase
    {
        virtual void log_header() = 0;
    }
};
#endif

Solution

  • With value types, you need to declare the object to be of type headerDerived:

    logfile::headerDerived Obj;
    Obj.log_header() >> "Add this text to my log file";
    

    with pointers, you need to allocate the actual object. In your code, you just have an unitialized pointer:

    logfile::headerBase *Obj;
    

    Obj points to some random memory location. You need to make it point to some actual object. That object can be a headerDerived:

    logfile::headerBase *Obj = new headerDerived;
    

    However, doing manual memory allocation like this is not recommended, because then you also need to manually delete the object again when you don't need it anymore:

    delete Obj;
    

    If you don't get it right, you will leak the object (there's no garbage collector in C++.) So you should either use value types, or smart pointers (like shared_ptr or unique_ptr):

    #include <memory>
    
    // ...
    
    std::shared_ptr<logfile::headerBase> Obj = std::make_shared<logfile::headerDerived>();
    Obj->log_header();
    

    In any event, you should just use value types, not pointers, unless you actually have a reason not to. Polymorphism still works with value types if you pass the objects by reference or by pointer. This works fine, for example:

    void by_reference(logfile::headerBase& obj)
    {
        obj.log_header() >> "Add this text to my log file";
    }
    
    void by_pointer(logfile::headerBase* obj)
    {
        obj->log_header() >> "Add this text to my log file";
    }
    
    
    // ...
    
    logfile::headerDerived Obj;
    by_reference(Obj);
    by_pointer(&Obj);
    

    You would use smart pointers instead of value types if you wanted to objects you create to outlive the scope they were created in. For example if you pass the object to function, and that function needs to store a pointer to the object for later use, then you must not use a value type. You need to allocate the object on the heap, and for that you use a smart pointer like shared_ptr (or unique_ptr if there's ever only one owner of the object, but if unsure, use shared_ptr.)