关于c ++:实现虚函数时对vtable的未定义引用


Undefined reference to vtable while implementing virtual functions

本问题已经有最佳答案,请猛点这里访问。

我尝试用杰西自由和Tim Keogh来实现"C++编程入门"的例子,但是实现纯虚拟函数是编译而不是构建。它给出了错误:未定义对"vtable for circle"的引用

我试过用变量itsRadius代替虚拟函数GetItsRadius,看它是否能工作,但它开始给我在switch语句中的错误,但RectangleSquare的错误是一样的,而且和以前的circle的错误也是一样的。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <iostream>

using namespace std;

enum BOOL { FALSE, TRUE };

class Shape
{
    public:
        Shape(){}
        ~Shape(){}
        virtual long GetArea() = 0; // error
        virtual long GetPerim()= 0;
        virtual void Draw() = 0;
    private:
};

void Shape::Draw()
{
    cout <<"Abstract drawing mechanism!
"
;
}

class Circle : public Shape
{
    public:
        Circle(int radius):itsRadius(radius){}
        ~Circle(){}
        long GetArea() { return 3 * itsRadius * itsRadius; }
        long GetPerim() { return 9 * itsRadius; }
        void Draw();
    private:
        int itsRadius;
        int itsCircumference;
};

class Rectangle : public Shape
{
    public:
        Rectangle(int len, int width):
        itsLength(len), itsWidth(width){}
        ~Rectangle(){}
        long GetArea() { return itsLength * itsWidth; }
        long GetPerim() { return 2*itsLength + 2*itsWidth; }
        virtual int GetLength() { itsLength; }
        virtual int GetWidth() { itsWidth; }
        void Draw();
    private:
        int itsWidth;
        int itsLength;
};

void Rectangle::Draw()
{
    for (int i = 0; i<itsLength; i++)
    {
        for (int j = 0; j<itsWidth; j++)
            cout <<"x";

        cout <<"
"
;
    }
    Shape::Draw();
}

class Square : public Rectangle
{
    public:
        Square(int len);
        Square(int len, int width);
        ~Square(){}
        long GetPerim() {return 4 * GetLength();}
};

Square::Square(int len):
    Rectangle(len,len)
{}

Square::Square(int len, int width):
    Rectangle(len,width)
{
    if (GetLength() != GetWidth())
        cout <<"Error, not a square... a Rectangle??
"
;
}

void startof()
{
    int choice;
    BOOL fQuit = FALSE;
    Shape * sp;

    while (1)
    {
        cout <<"(1)Circle (2)Rectangle (3)Square (0)Quit:
"
;
        cin >> choice;

        switch (choice)
        {
            case 1: sp = new Circle(5);
                break;
            case 2: sp = new Rectangle(4,6);
                break;
            case 3: sp = new Square (5);
                break;
            default: fQuit = TRUE;
                break;
        }
        if (fQuit)
            break;

        sp->Draw();
        cout <<"
"
;
    }
}


int main()
{
    startof();
}


这里的问题是您没有定义函数Circle::Draw()。如果你定义了它,代码就会编译。

另外,您应该使Shape析构函数为虚拟的(否则,在某些情况下,派生类的实例可能不会被正确地销毁)。这里的规则是,如果一个类有任何虚拟成员,那么析构函数也应该是虚拟的。

我知道你看到的编译消息非常神秘。我曾经看到过这样的场景:这个"未定义的v-table"编译器错误是其他一些问题的副作用,比如在本例中。让您知道,消除此错误的一个好方法是将受影响类的一个虚拟函数定义移出行(我使用上面的circle析构函数进行了此操作,先将shape析构函数设为virtual)。这揭示了一个更好的编译器错误的真正问题。