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++ 中还包括 &lt;cstdio&gt; 而不是 &lt;stdio.h&gt;

为您的 Shape 类为 1 创建一个虚拟析构函数:

 class Shape 
 public:
    virtual ~Shape() 
    ...
 ;

enum class 用于问题2 中的enum。普通的enums 没有作用域。

使用-std=c++11 来使用更现代的标准。 GCC 6 已经默认为C++14

【讨论】:

GCC 前端程序gcc 可以编译C 和C++ 文件,它使用文件后缀来确定它是什么类型的源。但是,它不会与 C++ 运行时库链接,这是一个问题。 哇,为什么我没有注意到这一点,我不明白你的第二部分包含。你介意改写吗?非常感谢德国人! 使用 #include 而不是 #include 。 Mac 有相当老的 gcc 版本。 Mac 没有 any 版本的 gcc。它有 clang(当你安装 Xcode 命令行工具时),它是 WRT LLVM 自己的最新版本。

以上是关于gcc:架构 x86_64 的未定义符号,缺少 vtable的主要内容,如果未能解决你的问题,请参考以下文章

MATLAB:mex-compile 上缺少框架 – 架构 x86_64 的未定义符号

架构 x86_64 的未定义符号:El Capitan [重复]

mac上的架构x86_64错误的未定义符号

架构 x86_64 / i386 的未定义符号

Quickblox:架构 x86_64 的未定义符号:错误

GoogleMapsSDK:架构 x86_64 的未定义符号