C++'s pure virtual function implementation and header files
Asked Answered
C

3

13

I'm having some trouble implementing pure virtual functions inherited from some abstract class, when the classes in question are divided into *.h and *.cpp files. The compiler (g++) tells me that the derived class cannot be instantiated because of the existence of pure functions.

/** interface.h**/
namespace ns
{
    class Interface {
        public:
            virtual void method()=0;
    }
}

/** interface.cpp**/
namespace ns
{
    //Interface::method()() //not implemented here
}

/** derived.h **/
namespace ns
{
    class Derived : public Interface {
        //note - see below
    }
}

/** derived.cpp **/
namespace ns
{
    void Derived::Interface::method() { /*doSomething*/ }
}

/** main.cpp **/
using namespace ns;
int main()
{
    Interface* instance = new Derived; //compiler error
}

Does this mean that I have to declare the method() twice - in the Interface's *.h and in the derived.h too? Is there no other way around?

Crutchfield answered 13/1, 2011 at 0:29 Comment(1)
First, there's no reason to have a .cpp file in which the only thing is a blank namespace. You don't need an implementation file for a header congaing an abstract class.Slier
E
16

You forgot to declare Derived::method().

You tried to define it at least, but wrote Derived::Interface::method() rather than Derived::method(), but you did not even attempt to declare it. Therefore it doesn't exist.

Therefore, Derived has no method(), therefore the pure virtual function method() from Interface was not overridden... and therefore, Derived is also pure virtual and cannot be instantiated.

Also, public void method()=0; is not valid C++; it looks more like Java. Pure virtual member functions have to actually be virtual, but you did not write virtual. And access specifiers are followed by a colon:

public:
    virtual void method() = 0;
Evelyn answered 13/1, 2011 at 0:34 Comment(5)
The void bit probably a typo, it's not java either.Moser
@time4tea: Indeed it's not valid Java either, but with the missing colon and the implication that the access specifier has been seen as something joined to the declaration, it's a damn sight closer than it is to C++!Evelyn
The syntax was my typo, see my comment to the opening post :) sorry about that. Also, the Derived::Interface::method() is my attempt to define a function that should be inherited from Interface. My original question was something along the lines "can I implement (define) an inherited pure virtual function without explicitly declaring it in the derived class's .h file?". The reason I'd like to do that is to avoid cluttering my header file when the class inherits from several interfaces, containing several pure virtuals each...Crutchfield
@Neo: And the answer is no. :)Evelyn
@Thomalak Geret'kal: Ah. Pity. :( Thanks a lot for your help :)Crutchfield
T
18

You have to declare your method in the subclass.

// interface.hpp
class Interface {
public:
    virtual void method()=0;
}

// derived.hpp
class Derived : public Interface {
public:
    void method() override;
}

// derived.cpp
void
Derived::method()
{
    // do something
}
Terisateriyaki answered 13/1, 2011 at 0:34 Comment(4)
I think you mean declare (not define).Mada
@MikeSlutsky yes I did.Terisateriyaki
@Terisateriyaki Thank you for the answer. Can you ellaborate on the reasons for that ? Coming from Java it seems very dirty to have to do that. When we have many derived different classes and many methods in the base interface we need to change a lot of files in case of change in the base interface.Corycorybant
@ManuelSelva you can't define a method in a class unless it's declared in that class. This is independent of whether this class derives from anything.Terisateriyaki
E
16

You forgot to declare Derived::method().

You tried to define it at least, but wrote Derived::Interface::method() rather than Derived::method(), but you did not even attempt to declare it. Therefore it doesn't exist.

Therefore, Derived has no method(), therefore the pure virtual function method() from Interface was not overridden... and therefore, Derived is also pure virtual and cannot be instantiated.

Also, public void method()=0; is not valid C++; it looks more like Java. Pure virtual member functions have to actually be virtual, but you did not write virtual. And access specifiers are followed by a colon:

public:
    virtual void method() = 0;
Evelyn answered 13/1, 2011 at 0:34 Comment(5)
The void bit probably a typo, it's not java either.Moser
@time4tea: Indeed it's not valid Java either, but with the missing colon and the implication that the access specifier has been seen as something joined to the declaration, it's a damn sight closer than it is to C++!Evelyn
The syntax was my typo, see my comment to the opening post :) sorry about that. Also, the Derived::Interface::method() is my attempt to define a function that should be inherited from Interface. My original question was something along the lines "can I implement (define) an inherited pure virtual function without explicitly declaring it in the derived class's .h file?". The reason I'd like to do that is to avoid cluttering my header file when the class inherits from several interfaces, containing several pure virtuals each...Crutchfield
@Neo: And the answer is no. :)Evelyn
@Thomalak Geret'kal: Ah. Pity. :( Thanks a lot for your help :)Crutchfield
E
0

You also did not call constructor properly - it's also a method;

 Interface* instance = new Derived;

Should be

 Interface* instance = new Derived();
Eyeshot answered 3/3, 2022 at 4:2 Comment(1)
This is C++ and you certainly can create objects with both new Derived; and new Derived();. There's a certain difference between the two (see this answer ), but in this case they're equivalent because there are no fields to initialize.Crutchfield

© 2022 - 2024 — McMap. All rights reserved.