2013-02-18 71 views
1

我目前正在使用虚拟功能的用户程序。我只使用一个虚拟功能,并遇到了似乎是我尝试过的一个常见解决方案的常见问题,但不幸的是没有成功。未定义引用'typeinfo和'虚拟表

我最初有virtual void calcArea();在BasicShape.h中没有任何定义或指定为纯虚函数。我改变了它,并添加{}末(上有类似的问题,另一个线程的建议),但我仍然得到以下错误:

我输入:

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

然后我得到:

/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 

任何想法?

这是实现文件BasicShape.h:

#ifndef BASICSHAPE_H 
#define BASICSHAPE_H 

class BasicShape 
{ 
    protected: 
    double area; 

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

#endif 

所附BasicShape.cpp文件:

#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); 
} 

驱动程序是不完整的,但无关我的问题呢(至少我是这么认为的)。

#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; 
} 
+2

恕我直言,你应该先试着说明你的完整问题(包括错误信息,你期望的等),然后用大量代码文件吓跑人们。 – congusbongus 2013-02-18 00:29:26

+0

是的,它现在看起来有点威胁,现在我想到了它o_o thx的提示 – newwarrior21st 2013-02-18 00:31:54

回答

0

好吧,显然这似乎都是编译器问题。整个这段时间,我使用gedit作为文本编辑器,使用g ++作为编译器,但是当我切换到代码块时,它工作得很好。

1

你不应该tryo编译头:

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

+0

我只是试图编译它,但我得到相同的错误 – newwarrior21st 2013-02-18 00:32:23

+0

,因为你在构造函数中调用虚函数!!! 1 – billz 2013-02-18 00:37:01

+3

@billz:这不会导致链接错误。它有时会导致关于执行哪个函数的惊喜。 – aschepler 2013-02-18 00:44:23

2

事实上,正如有人指出,你有没有编译头。 (尽管你可以,但这里并不重要 - gcc会生成预编译头文件)。

更有趣的是:你的例子在这里完美的工作,GCC 4.6.3。

此外,旁注:油杉不应该是公共

+0

所以你认为这可能是g ++(我的编译器)专有的问题? – newwarrior21st 2013-02-18 00:39:35

+0

@ newwarrior21st:我认为你更可能意外地没有提到代码中的一些细微差别,或者你尝试去编译它。 (这些文件全都在同一个目录下,全部保存等?) – aschepler 2013-02-18 00:42:55

+1

好吧,看起来你的编译器不能在构造函数中处理虚函数(默认情况下这是坏事)。我建议修改你的代码,如下所示:make area volatile,在BasicShape()中初始化为-1;在所有嵌套的getArea()方法中,只需检查区域是否根本不缓存(区域== -1),然后重新计算此值。类似'double circle :: getArea(){if(-1 == area)calcArea();返回区域; }' – MPogoda 2013-02-18 00:45:08

1

你的编译器需要其中一个虚拟构件类定义之外定义为每个多态类的至少一个翻译单元。只有存在这样的翻译单元时,它才会为该类实例化一些内部数据(虚拟函数表,多态类型信息)。

(免责声明:至少是这样的话,当我最后一次使用它,很久以前)

您既可以使用外的类的定义为BasicShape::calcArea功能或添加一个虚拟(可选甚至纯虚)析构函数到BasicShape并将其定义为超类。最好的地方可能是BasicShape.cpp文件。

顺便说一句:正如其他人指出的,你通常不应该将头文件作为独立的翻译单元传递给编译器。这不会损害(除了夸大你的编译时间),但也是没有好处的。

+0

你的意思是这样的: 无效BasicShape ::油杉(){ } 当我这样做,它给了我这样的: BasicShape.cpp: 11:6:错误:'void BasicShape :: calcArea()'的原型不匹配'BasicShape'中的任何类型 BasicShape.h:14:20:error:candidate is:virtual double BasicShape :: calcArea() – newwarrior21st 2013-02-18 01:00:25

+0

是,就像你为其他班级所做的那样。只需将它放入'.cpp'文件中,而不是在类定义内部定义它。 – JoergB 2013-02-18 01:03:07

+0

它看起来很有帮助,但编译器回应如下: BasicShape.cpp:11:6:错误:'void BasicShape :: calcArea()'的原型不匹配'BasicShape'中的任何类型 BasicShape.h: 14:20:error:candidate is:virtual double BasicShape :: calcArea() – newwarrior21st 2013-02-18 01:06:52

相关问题