简体   繁体   English

对`typeinfo和'vtable的未定义引用

[英]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(); 我最初有虚拟空洞calcArea(); in BasicShape.h without any definition or designation as a pure virtual function. 在BasicShape.h中没有任何定义或指定为纯虚函数。 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: 这是实现文件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: 随附的BasicShape.cpp文件:

#include "BasicShape.h"

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

void BasicShape::calcArea()
{
}

circle.h: 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: 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 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: 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). (虽然你可以,但这里无关紧要--- gcc会生成预编译的头文件)。

And more interesting: your example perfectly works here, GCC 4.6.3. 更有趣的是:你的例子完全适用于此,GCC 4.6.3。

Also, sidenote: calcArea shouldn't be public 另外,旁注:calcArea不应公开

You should not tryo to compile the headers: 你不应该尝试编译标题:

g++ BasicShape.cpp circle.cpp Rectangle.cpp driver.cpp -o Lab4 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. 你既可以使用外的类的定义为BasicShape::calcArea功能或虚拟(可选甚至纯虚)析构函数添加到BasicShape并将它定义外的类。 The best place would probably be the BasicShape.cpp file. 最好的地方可能是BasicShape.cpp文件。

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. 这整个时间我使用gedit作为文本编辑器和g ++作为编译器,但当我切换到代码块时它工作得很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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