-1

I have been trying to sort out this error for 3 hours now, and I have still not found anything wrong with my code. I have a class GrainLJ which inherits from an abstract class Grain. The class GrainLJ also has 2 subclasses GrainLJT1 and GrainLJT2.

The entire error:

g++ -std=c++11   -pedantic -Wall        -g                       -c -o GrainLJTUn.o GrainLJTUn.cc
g++   testGrain.o Vecteur3D.o GrainLJTUn.o   -o testGrain
testGrain.o: In function `GrainLJ::~GrainLJ()':
/home/INTRANET/mushkaev/myfiles/cpp/projet/marche/marche/GrainLJ.h:18: undefined reference to `vtable for GrainLJ'
testGrain.o: In function `TextSupport::dessine(GrainLJ const&)':
/home/INTRANET/mushkaev/myfiles/cpp/projet/marche/marche/TextSupport.h:15: undefined reference to `operator<<(std::ostream&, GrainLJ const&)'
testGrain.o: In function `TextSupport::dessine(Plan const&)':
/home/INTRANET/mushkaev/myfiles/cpp/projet/marche/marche/TextSupport.h:17: undefined reference to `operator<<(std::ostream&, Plan const&)'
testGrain.o: In function `TextSupport::dessine(Source const&)':
/home/INTRANET/mushkaev/myfiles/cpp/projet/marche/marche/TextSupport.h:18: undefined reference to `operator<<(std::ostream&, Source const&)'
testGrain.o:(.rodata._ZTI9GrainLJT1[_ZTI9GrainLJT1]+0x10): undefined reference to `typeinfo for GrainLJ'
GrainLJTUn.o: In function `GrainLJT1::GrainLJT1(Vecteur3D, Vecteur3D, double, double, SupportADessin*)':
/home/INTRANET/mushkaev/myfiles/cpp/projet/marche/marche/GrainLJTUn.cc:14: undefined reference to `GrainLJ::GrainLJ(Vecteur3D, Vecteur3D, double, double, SupportADessin*)'
GrainLJTUn.o: In function `GrainLJ::GrainLJ(GrainLJ const&)':
/home/INTRANET/mushkaev/myfiles/cpp/projet/marche/marche/GrainLJ.h:12: undefined reference to `vtable for GrainLJ'
collect2: error: ld returned 1 exit status
make: *** [testGrain] Error 1

Here is the code:

testGrain.cc:

#include <iostream>
#include "Vecteur3D.h"
#include "GrainLJTUn.h"


using namespace std;



int main(){
    Vecteur3D vitesse(1,2,3);
    Vecteur3D position(2,3,4);

    GrainLJT1 d(position,vitesse,5.0,9.0);

    //cout << d;

    return 0;
}

GrainLJ.h:

#ifndef PRJ_GRAINLJ_H
#define PRJ_GRAINLJ_H

#include <iostream>
#include <cmath>
#include "plan.h"
#include "Grain.h"
#include "Vecteur3D.h"
#include "SupportADessin.h"
#include <memory>

class GrainLJ : public Grain{ //GrainLJ n'est plus abstraite.

    protected:
        static double epsilon;// au cas j'ai mis une valeur au pif en attendant dans le .cc
        static double sigma;
    public:
        virtual ~GrainLJ(){}
        GrainLJ(Vecteur3D p = Vecteur3D(), Vecteur3D v = Vecteur3D(), double m = 0, double r = 0, SupportADessin* sup = nullptr);
        double forceLJ(double eij) const;
        void ajouteForce(GrainLJ*);
        void ajouteForce(Vecteur3D);
        void ajouteForce(Plan*);
        virtual std::unique_ptr<GrainLJ> copie() const;
        virtual void dessine() override{ if (support != nullptr) support->dessine(*this);}
};
std::ostream& operator<<(std::ostream&, GrainLJ const&);
#endif // PRJ_GRAINLJ_H

GrainLJT1

#ifndef PRJ_GRAINLJTUN_H
#define PRJ_GRAINLJTUN_H
#include "GrainLJ.h"
#include <iostream>
#include <memory>
#include "Vecteur3D.h"

class GrainLJT1 : public GrainLJ{
    public:
            ~GrainLJT1(){}
            GrainLJT1(Vecteur3D p = Vecteur3D(), Vecteur3D v = Vecteur3D(), double m = 0, double r = 0, SupportADessin* sup = nullptr);

            virtual void dessine() override{ 

            if(support != nullptr){ 

                std::cout << "Grain LJ de type 2: "; 
                GrainLJ::dessine();
            }
        }
        virtual std::unique_ptr<GrainLJ> copie() const override{return cloneMe();}
        std::unique_ptr<GrainLJT1> cloneMe() const;

}; 

#endif // PRJ_GRAINLJTUN_H

I apologize in advance if this is too much code to post in one go. I can post other bits if requested.

EDIT:

As requested, here are the class definitions of TextSupport and Grain. Grain is an abstract class, as it inherits a pure virtual method dessine() (draw) from Dessinable (Drawable). The latter superclass contains the method dessine(), a virtual destructor and a certain parameter in protected (a pointer to SupportADessin (a generalised drawing class)). TextSupport is a class which enables 'textual drawing' in a sense that it contains the different draw methods for different 'drawable' classes such as GrainLJ, Plan and Source which all inherit from Dessinable.

#ifndef PRJ_TEXT_SUPPORT_H
#define PRJ_TEXT_SUPPORT_H

#include "SupportADessin.h"
#include "plan.h"
#include "Source.h"
#include <iostream>
#include "GrainLJ.h"

class TextSupport: public SupportADessin{


        public:
        ~TextSupport() {}
        void dessine(GrainLJ const& g) override{std::cout << g << std::endl;} 
        void dessine(Plan const& p) override{std::cout << p << std::endl;}
        void dessine(Source const& s) override{std::cout << s << std::endl;}

};
#endif // PRJ_TEXT_SUPPORT_H

#ifndef PRJ_GRAIN_H
#define PRJ_GRAIN_H

#include "Vecteur3D.h"
#include "SupportADessin.h"
#include "Dessinable.h"
#include <memory>

class Grain: public Dessinable{    // j'ai enlevé l'opérateur de grain et remplacé grainLJ, vu que grain est abstrait.

    public:
        Grain(Vecteur3D position = Vecteur3D(), Vecteur3D vitesse = Vecteur3D(), double masse_vol = 0, double rayon = 0, SupportADessin* sup = nullptr);

        ~Grain(){}
        double masse() const;
        Vecteur3D get_pos() const;
        Vecteur3D get_vit() const;
        SupportADessin* get_sup() const;
        double get_massev() const;
        double get_rayon() const ;
        double lambda() const;
        void ajouteForce();
        void bouger(double dt);
        void set_vitesse(double x, double y, double z);
        void set_rayon(double r);
        //std::unique_ptr<Grain> cloneMe() const;
        //virtual std::unique_ptr<Dessinable> copie() const;

    protected:
        Vecteur3D position;
        Vecteur3D vitesse;
        double masse_vol;
        double rayon;
        Vecteur3D force;

};

#endif // PRJ_GRAIN_H
Ruslan Mushkaev
  • 1,005
  • 1
  • 7
  • 10
  • https://gcc.gnu.org/faq.html#vtables – ifma May 06 '17 at 16:27
  • yes can you post the class definition of grain and the function TextSupport which appears in the errors? – didiz May 06 '17 at 16:54
  • 1
    Three hours isn't a very long time. You haven't had enough time to construct a [MCVE] yet. Go ahead and do that now. (Two years' membership is long enough to know that we require that.) – Lightness Races in Orbit May 06 '17 at 17:09
  • `undefined reference to \`operator<<(std::ostream&, Plan const&)'` suggests that there might be a problem in `plan.h`, or that an object file might be missing. Are you sure you linked against every object file, and can you make sure all of the mentioned functions are defined where you expect them to be defined? – Justin Time - Reinstate Monica May 06 '17 at 17:10
  • @BoundaryImposition I understand. However, as you can see from the testfile, I am not even able to create an object of class GrainLJT1 without getting these errors. Concerning the necessary headers, I am really not sure which ones contribute and which ones do not, hence the slightly lengthy code. – Ruslan Mushkaev May 07 '17 at 08:34
  • @didiz please see the edit – Ruslan Mushkaev May 07 '17 at 09:06
  • Undefined references to vtables happen when you forgot to override a pure virtual function. But apparently said function is in `Dessinable`, which you haven't included... – Quentin May 07 '17 at 09:21
  • _"Concerning the necessary headers, I am really not sure which ones contribute and which ones do not, hence the slightly lengthy code."_ Right, then find out, by constructing a [MCVE]. This debugging phase is your responsibility not ours – Lightness Races in Orbit May 07 '17 at 12:19

2 Answers2

0

All classes deriving from an abstract class must implement the pure virtual functions. They cannot inherit it and pass it forward.

The solution is to add an implementation to each derived class, or to make dessinable function just virtual.

Deriving a class from an abstract class (C++)

Community
  • 1
  • 1
didiz
  • 1,069
  • 13
  • 26
  • But the method dessine() in superclass Dessinable is pure virtual. I have purposefully not defined it in Grain (inherits from Dessinable) to make Grain abstract, but have redefined it in GrainLJ (inherits from Grain) to make it 'not-abstract'. – Ruslan Mushkaev May 07 '17 at 09:22
  • Because it is pure virtual, it forces all derived classes to override it. That is your compile error – didiz May 07 '17 at 09:29
  • But doesnt providing Grain with the implementation of the method make it no longer abstract? (I want Grain to be abstract). In the link provided, it is stated that a base class can have a definition of a pure virtual function inside that class. But since Grain is not a base class, I cant therefore make the method dessine() remain pure virtual and be defined inside Grain, right? – Ruslan Mushkaev May 07 '17 at 10:18
  • You can define another pure virtual function on Grain, that would make it abstract as well. – didiz May 07 '17 at 10:39
-5
#ifndef PRJ_GRAINLJ_H
#define PRJ_GRAINLJ_H

#include <iostream>
#include <cmath>
#include "plan.h"
#include "Grain.h"
#include "Vecteur3D.h"
#include "SupportADessin.h"
#include <memory>
class Grain;//u lost this
class GrainLJ : public Grain{ //GrainLJ n'est plus abstraite.

    protected:
        static double epsilon;// au cas j'ai mis une valeur au pif en attendant dans le .cc
        static double sigma;
    public:
        virtual ~GrainLJ(){}
        GrainLJ(Vecteur3D p = Vecteur3D(), Vecteur3D v = Vecteur3D(), double m = 0, double r = 0, SupportADessin* sup = nullptr);
        double forceLJ(double eij) const;
        void ajouteForce(GrainLJ*);
        void ajouteForce(Vecteur3D);
        void ajouteForce(Plan*);
       virtual std::unique_ptr<GrainLJ> copie() const;
        virtual void dessine() override{ if (support != nullptr) support->dessine(*this);}
};
std::ostream& operator<<(std::ostream&, GrainLJ const&);
#endif // PRJ_GRAINLJ_H
tgw
  • 1
  • How does this answer the question? And what makes you think that a forward declaration fixes a linker error? (assuming that is what your answer is getting at, hard to tell without you providing actual explanations) – UnholySheep May 06 '17 at 16:45
  • please explain your answer. – bolov May 06 '17 at 16:46
  • 2
    The only difference I can see between your version of `GrainLJ.h` and his is that you added the line `class Grain;//u lost this`. I'm 99% sure this is blatantly incorrect, considering he already `#include`d `Grain.h`. Also, if he had forgotten to declare or define `Grain` beforehand, it would've failed during compilation, and wouldn't have even gotten to the linking phase. – Justin Time - Reinstate Monica May 06 '17 at 17:13