Home > Software design >  How to avoid multiple definition of overridden method
How to avoid multiple definition of overridden method

Time:04-02

I have a Base class and a Derived class (which derives from the Base class). Both classes have a method called "getNumber ()".

In my main (), I want to run the method "getNumber()" of the Derived class. My main instantiates an object of the Animal class. In the Animal class is member variable : a pointer to the Base class, called "base". However, in the constructor for the Animal class, I want to set that "base" pointer to an object of type Derived.

However, when I try comppile this, I get the following error message:

Animal.cc:(.text 0x0): multiple definition of `Derived::getNumber()'; /tmp/ccwfn1zo.o:Derived.cc:(.text 0x0): first defined here
/usr/bin/ld: /tmp/ccwfn1zo.o: in function `Derived::~Derived()':
Derived.cc:(.text._ZN7DerivedD2Ev[_ZN7DerivedD5Ev] 0x26): undefined reference to `Base::~Base()'
/usr/bin/ld: /tmp/ccwfn1zo.o:(.data.rel.ro._ZTI7Derived[_ZTI7Derived] 0x10): undefined reference to `typeinfo for Base'
/usr/bin/ld: /tmp/ccpsXsim.o: in function `Derived::Derived()':
Animal.cc:(.text._ZN7DerivedC2Ev[_ZN7DerivedC5Ev] 0x18): undefined reference to `Base::Base()'
collect2: error: ld returned 1 exit status

Here is the main:

#include <iostream>
#include "Animal.h"
#include "Base.h"

using namespace std;


int main()
{
    Animal * a = new Animal;
    cout << a->base->getNumber();
}

Here is the code of the Base class in Base.h:

class Base {
public:
    Base ();
    virtual ~Base ();
public:
    virtual unsigned int getNumber() {
        return 1;
    }
};

Here is the code of the Derived.cc:

#include "Base.h"

class Derived : public Base {

public:
    ~Derived () {}
    
public:
    unsigned int getNumber () override;
   
};

unsigned int Derived::getNumber () {
    return 5;
}

Here is the code of Animal.h

class Base;

class Animal {
public:
    Animal ();
    ~Animal ();
  
public:
    Base* base = nullptr;
};

And finally Animal.cc

#include "Animal.h"
#include "Derived.cc"

Animal::Animal () {
    base = new Derived;
}

What am I doing wrong ? I think its something basic, but I don't see it.

CodePudding user response:

The problem is that you're including a source file named Derived.cc instead of a header file. This results in multiple definition error because this source file is then included (directly and indirectly) into other files and so there are "multiple definition" for the mentioned member function Derived::getNumber().

To solve this, you should instead create a header file called Derived.h that will contain the declarations of the member functions and a separate source file that will contain the implementations of those member functions as shown below. Working Demo

main.cpp

#include <iostream>
#include "Animal.h"
#include "Base.h"

int main()
{
    Animal * a = new Animal;
    std::cout << a->base->getNumber();
}

Base.h

#include <iostream>
#include "Animal.h"
#include "Base.h"

int main()
{
    Animal * a = new Animal;
    std::cout << a->base->getNumber();
}

Base.cc

#include "Base.h"

Base::Base()
{
    
}
Base::~Base()
{
    
}

Animal.h

class Base;

class Animal {
public:
    Animal ();
    ~Animal ();
  
public:
    Base* base = nullptr;
};

Animal.cc

#include "Animal.h"
#include "Derived.h"

Animal::Animal () {
    base = new Derived;
}

Derived.h

#include "Base.h"

class Derived : public Base {

public:
    ~Derived () {}
    
public:
    unsigned int getNumber () override;
   
};


Derived.cc

#include "Derived.h"
unsigned int Derived::getNumber () {
    return 5;
}

Working Demo

Note: We should not include source files.

CodePudding user response:

Including source files like

#include "Derived.cc"

is a bad practice. Instead, put everything that should be seen from multiple source files in header files and include the header files.

In this case, you should create a new header file Derived.h and move the declaration of class Derived to the header file. The definition of the function Derived::getNumber should remain in Derived.cc.

  • Related