简体   繁体   中英

undefined reference to `typeinfo and 'vtable

i'm currently working on a program that employs the user of virtual functions. I am using only one virtual function and have come across what seems to be a common problem with a common solution which I have tried but unfortunately to no success.

I originally had virtual void calcArea(); in BasicShape.h without any definition or designation as a pure virtual function. I changed it and added {} at the end (as suggested on another thread with a similar problem) but I still get the following error:

I input:

g++ BasicShape.h BasicShape.cpp circle.h circle.cpp Rectangle.h Rectangle.cpp driver.cpp -o Lab4

And then I get:

/tmp/ccf1Y4Br.o: In function `BasicShape::BasicShape()': circle.cpp:(.text._ZN10BasicShapeC2Ev[_ZN10BasicShapeC5Ev]+0xf): undefined reference to `vtable for BasicShape'
/tmp/ccf1Y4Br.o:(.rodata._ZTI6circle[_ZTI6circle]+0x10): undefined reference to `typeinfo for BasicShape'
/tmp/ccc7gjtH.o:(.rodata._ZTI9Rectangle[_ZTI9Rectangle]+0x10): undefined reference to `typeinfo for BasicShape'
collect2: error: ld returned 1 exit status

Any ideas?

This is the implementation file BasicShape.h:

#ifndef BASICSHAPE_H
#define BASICSHAPE_H

class BasicShape 
{
  protected: 
    double area;

  public:
    double getArea() const;
     virtual void calcArea();
};

#endif

The accompanying BasicShape.cpp file:

#include "BasicShape.h"

double BasicShape::getArea() const
{
  return area;
}

void BasicShape::calcArea()
{
}

circle.h:

#include "BasicShape.h"

#ifndef CIRCLE_H
#define CIRCLE_H

class circle : public BasicShape
{
  private:
    long centerX;
    long centerY;
    double radius;

  public:
    circle(long, long, double);
    long getCenterX() const;
    long getCenterY() const;
    virtual void calcArea();
};

#endif

circle.cpp:

#include "circle.h"

// constructor
circle::circle(long userIn, long userIn2, double userIn3)
{
  centerX = userIn;
  centerY = userIn2;
  radius = userIn3;
  calcArea();
}

// accesors
long circle::getCenterX() const
{
  return centerX;
}

long circle::getCenterY() const
{
  return centerY;
}

// virtual function
void circle::calcArea()
{
  area = (3.14159 * radius * radius);
}

Rectangle.h

#include "BasicShape.h"

#ifndef RECTANGLE_H
#define RECTANGLE_H

class Rectangle : public BasicShape
{
  private:
    long width;
    long length;

  public:
    Rectangle(long, long);
    long getWidth() const;
    long getLength() const;
    virtual void calcArea();
};

#endif

Rectangle.cpp:

#include "Rectangle.h"

// constructor
Rectangle::Rectangle(long userIn, long userIn2)
{
  width = userIn;
  length = userIn2;
  calcArea();
}

// accessors
long Rectangle::getWidth() const
{
  return width;
}

long Rectangle::getLength() const
{
  return length;
}

void Rectangle::calcArea()
{
  area = (length * width);
}

The driver program is incomplete, but irrelevant to my problem anyway (at least I think so).

#include <cassert>
#include <iostream>
#include "BasicShape.h"
#include "Rectangle.h"
#include "circle.h"
using namespace std;

int main()
{

  cout << "Testing the functionality and efficiency of the circle class...\n";
  // declare circle object and test accessors and area computation
  circle objCircle(8,8,4);
  assert(objCircle.getCenterX() == 8);
  assert(objCircle.getCenterY() == 8);
  assert(objCircle.getArea() == 50.26544);
  cout << "Circle object testing completed successfully\n";

  cout << "Testing the functionality and efficiency of the Rectangle class...\n";
  // declare rectangle object and test accessors and area computation  
  //Rectangle objRec();

  return 0;
}

Actually, as it was pointed out, you have not to compile headers. (Although you can, it is irrelevant here --- gcc will generate precompiled headers).

And more interesting: your example perfectly works here, GCC 4.6.3.

Also, sidenote: calcArea shouldn't be public

You should not tryo to compile the headers:

g++ BasicShape.cpp circle.cpp Rectangle.cpp driver.cpp -o Lab4

Your compiler needs at least one translation unit where a virtual member is defined outside the class definition for each polymorphic class. It will instantiate some internal data for the class (virtual function table, polymorphic typeinfo) only if there is such a translation unit.

(Disclaimer: At least that was the case when I last used it, long ago)

You could either use an out-of-class definition for the BasicShape::calcArea function or add a virtual (optionally even pure virtual) destructor to BasicShape and define it out-of-class. The best place would probably be the BasicShape.cpp file.

BTW: As others have pointed out, you typically should not pass header files as separate translation units to the compiler. This will do no harm (other than inflate your compilation time), but also no good.

Ok, so apparently this all seems to be a compiler issue. This entire time I was using gedit as a text editor and g++ as a compiler, but when I switched over to code blocks it was working just fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM