views:

44

answers:

3

It's late at night here and I'm going crazy trying to solve a linker error.

If I have the following abstract interface:

class IArpPacketBuilder
{
public:

    IArpPacketBuilder(const DslPortId& aPortId);
    virtual ~IArpPacketBuilder();

    // Other abstract (pure virtual methods) here...
};

and I instantiate it like this:

class DummyArpPacketBuilder
    : public IArpPacketBuilder
{

public:

    DummyArpPacketBuilder(const DslPortId& aPortId)
        : IArpPacketBuilder(aPortId) {}
    ~DummyArpPacketBuilder() {}
};

why am I getting the following error when linking?

Unresolved symbol references:

IArpPacketBuilder::IArpPacketBuilder(DslPortId const&):
    ppc603_vxworks/_arpPacketQueue.o
IArpPacketBuilder::~IArpPacketBuilder():
    ppc603_vxworks/_arpPacketQueue.o
typeinfo for IArpPacketBuilder:
    ppc603_vxworks/_arpPacketQueue.o
*** Error code 1

IArpPacketBuilder is an abstract interface, so as long as I define the constructors and destructions in the concrete (derived) interface, I should be fine, no? Well it appears not.

A: 

try inline them - works for me although don't know if it's good solution

XAder
you mean provide inline implementations in IArpPacketBuilder?
LeopardSkinPillBoxHat
yes, very the same way Peter has answered
XAder
+3  A: 

You have only declared the constructor and destructor of IArpPacketBuilder, not defined them. The linker needs the definitions too. Note that C++ has no concept of abstract interface - IArpPacketBuilder is a plain old class which happens to contain some pure virtual methods, thus making its direct instantiation impossible.

So the simplest solution is to provide inline implementations:

class IArpPacketBuilder
{
public:

    IArpPacketBuilder(const DslPortId& aPortId) {}
    virtual ~IArpPacketBuilder() {}

    // Other abstract (pure virtual methods) here...
};

You can also make the destructor pure virtual, but even so, you still need to provide a definition for it, e.g.

class IArpPacketBuilder
{
public:

    IArpPacketBuilder(const DslPortId& aPortId) {}
    virtual ~IArpPacketBuilder() = 0;

    // Other abstract (pure virtual methods) here...
};

IArpPacketBuilder::~IArpPacketBuilder() {}
Péter Török
I've been able to inherit from this interface in another library without any problems, so didn't think that would be a problem. Do I need to define them in an abstract interface?
LeopardSkinPillBoxHat
@Leopard, interesting. I thought it would not work that way - if you explicitly declare a constructor/destructor, the compiler won't generate it for you automatically. Note that C++ has no concept of _abstract interface_ - your class is a plain class with some pure virtual methods, which make its direct instantiation impossible.
Péter Török
@Peter - Thanks, I got it working by defining the bodies of the ctor and dtor, but I still can't understand why it worked in another library when I hadn't defined the ctor and dtor.
LeopardSkinPillBoxHat
@Peter - I just figured it out. I had a .cpp file for the interface which DID define the ctor and dtor, but when I inherited from the interface in another library, I didn't link against that .cpp file which is why I got the unresolved symbols. Silly mistake!
LeopardSkinPillBoxHat
@Leopard, that's one less mystery then... the Order of Things is recovered :-)
Péter Török
+1  A: 

You need to provide definitions - i.e. code bodies for both the constructor and destructor for the abstract interface class - both functions will be used in your code, even though the class is abstract. An abstract class is not one which is never instantiated - it is one that is never directly instantiated by the user. It will however be instantiated by the compiler, which needs the constructor and destructor to be defined.

anon