gcc:架构 x86_64 的未定义符号,缺少 vtable
Posted
技术标签:
【中文标题】gcc:架构 x86_64 的未定义符号,缺少 vtable【英文标题】:gcc: undefined symbols for architecture x86_64, missing vtable 【发布时间】:2016-05-19 06:54:51 【问题描述】:我正在尝试在我的mac book pro 15上做一些基本的c++继承+抽象方法程序,gcc信息如下。
gcc:
mmcmbp:cpp-shapes abe$ gcc -v
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/c++/4.2.1
Apple LLVM version 7.3.0 (clang-703.0.29)
Target: x86_64-apple-darwin15.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
代码:
/**
* @file main.cpp
* c plus plus implementation of shape and triangle inheritance.
*
* @brief Shape and Triangle implementation
*
* @author abraham cabrera
*
* @version 1.00
*/
#include <stdio.h>
/**
* @class Shape
*/
class Shape
public:
/** an enum of shape type
* Shape type representation
*/
enum ShapeType base, triangle ;
/* Default Shape constructor */
Shape()
this->type = base;
/**
* Shape constructor with type input.
*
* @param[in] type the shape type
*/
Shape(ShapeType type)
this->type = type;
/**
* Get type of Shape
*
* @return shape type
*/
int getType()
return this->type;
/**
* Mutator for setting the shape type.
*
* @param[in] type shape type
* @return void
*/
void setType(ShapeType type)
this->type = type;
virtual int area()
return 0;
private:
ShapeType type; //< Type of shape.
;
class Rectangle: public Shape
public:
/**
* Rectangle Constructor
*
* @param[in] length length of rectangle
* @param[in] width width of rectangle
*/
Rectangle(int length, int width) : Shape(Shape::ShapeType::triangle)
this->length = length;
this->width = width;
/**
* Gets the length of the Rectangle.
*
* @return length
*/
int getLength()
return this->length;
/**
* Gets the width of the Rectangle
*
* @return width
*/
int getWidth()
return this->width;
/**
* Sets the length of the Rectangle
*
* @param[in] length
* @return void
*/
void setLength(int length)
this->length = length;
/**
* Sets the width of the Rectangle
*
* @param[in] width
* @return void
*/
void setWidth(int width)
this->width = width;
/**
* Calculates the Area of a Rectangle
*
* @return length * width
*/
int area()
return this->length * this->width;
private:
int length; //< The length of the Rectangle
int width; //< The width of the Rectangle
;
int main()
Rectangle rectangle = Rectangle(4, 3);
printf("Rectangle %i\n", rectangle.area());
printf("width %i, length %i\n", rectangle.getWidth(), rectangle.getLength());
return 0;
我想我在这里没有正确理解 c++ 虚函数,因为当我尝试从上面编译我的小代码 sn-p 时,我收到以下错误和警告。
mmcmbp:cpp-shapes abe$ gcc main.cpp -o main
main.cpp:71:51: warning: use of enumeration in a nested name specifier is a C++11 extension [-Wc++11-extensions]
Rectangle(int length, int width) : Shape(Shape::ShapeType::triangle)
^
1 warning generated.
Undefined symbols for architecture x86_64:
"vtable for __cxxabiv1::__class_type_info", referenced from:
typeinfo for Shape in main-6841d5.o
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
"vtable for __cxxabiv1::__si_class_type_info", referenced from:
typeinfo for Rectangle in main-6841d5.o
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
问题:
显然我不理解导致我提出第一个问题的错误部分。
-
我上面提到的错误到底是什么意思?
至于一个附带问题,因为我有点好奇。
-
为什么我会收到以下警告
warning: use of enumeration in a nested name specifier is a C++11 extension
?
非常感谢您最亲切的意见。
谢谢,
-安倍。
【问题讨论】:
如果你使用继承,你真的应该提供虚拟析构函数。 我认为在Shape
类中创建函数 area
会比返回 0 更好
我更新了我的答案,展示了如何使用 gcc 驱动程序而不是 g++ 进行编译。
另外你应该在 Mac 中使用 clang,因为 Apple 从 4.2 开始停止使用 gcc。
【参考方案1】:
-
您正在使用 gcc 编译 c++ 程序。 gcc 是 GNU C 编译器,你应该使用 g++ 来编译你的程序。
g++ main.cpp -o main
-
c++03 中的枚举没有作用域,所以你不能使用像
EnumType::EnumValue
这样的枚举。在 c++11 中,如果可以声明一个枚举,例如
enum class EnumType EnumValue ;
然后您就可以按照您的意愿使用它了。有关枚举的更多信息here
【讨论】:
GCC 前端程序gcc
可以编译C 和C++ 文件,它使用文件后缀来确定它是什么类型的源。但是,它不会与 C++ 运行时库链接,这是一个问题。
嗨 AdrianTut,非常感谢您满足我对枚举警告的好奇心。
@JoachimPileborg 可以链接。就像我展示的那样。但不建议这样做。【参考方案2】:
您应该使用 g++ 作为驱动程序来编译 c++ 代码。
g++ -std=c++11 ~/tmp/virt.cpp
或者
gcc -std=c++11 ~/tmp/virt.cpp -lstdc++
但前者是首选
您需要通过 -std=c++11 来禁用此警告,因为默认情况下 Mac 中的 gcc 不会为 c++11 编译。
【讨论】:
或者更好的是clang++
。【参考方案3】:
您可能正在使用 C 进行编译,请使用 g++
。在 C++ 中还包括 <cstdio>
而不是 <stdio.h>
。
为您的 Shape
类为 1 创建一个虚拟析构函数:
class Shape
public:
virtual ~Shape()
...
;
将enum class
用于问题2 中的enum
。普通的enum
s 没有作用域。
使用-std=c++11
来使用更现代的标准。 GCC 6 已经默认为C++14
。
【讨论】:
GCC 前端程序gcc
可以编译C 和C++ 文件,它使用文件后缀来确定它是什么类型的源。但是,它不会与 C++ 运行时库链接,这是一个问题。
哇,为什么我没有注意到这一点,我不明白你的第二部分包含。你介意改写吗?非常感谢德国人!
使用 #include以上是关于gcc:架构 x86_64 的未定义符号,缺少 vtable的主要内容,如果未能解决你的问题,请参考以下文章
MATLAB:mex-compile 上缺少框架 – 架构 x86_64 的未定义符号