22

我是 C++ 编程的新手,但已经在 C 和 Java 领域工作了很长时间。我正在尝试在我正在处理的一些串行协议中做一个类似接口的层次结构,并不断收到错误:

Undefined reference to 'operator delete(void*)'

(简化)代码如下:

PacketWriter.h:

class PacketWriter {
public:
    virtual ~PacketWriter() {}
    virtual uint8_t nextByte() = 0;
}

字符串编写器.h:

class StringWriter : public PacketWriter {
public:
    StringWriter(const char* message);
    virtual uint8_t nextByte();
}

构造函数和 nextByte 函数在 StringWriter.cpp 中实现,但仅此而已。我需要能够从指向 PacketWriter 的指针中删除 StringWriter,如果我为 StringWriter 定义了一个析构函数,无论是否虚拟,我都会遇到各种其他类似的错误。我确信这是一个简单的问题,我作为新手忽略了。

另外,我正在为 AVR 芯片编写这个,在 Windows 上使用 avr-g++。

谢谢

4

4 回答 4

38

很抱歉在旧帖子中发帖,但它在 Google 的搜索结果中仍然很高,如果你有这个问题,你真的应该看看这个链接,因为它说你只需要链接 -lstdc++,这就是解决对我来说问题。

社区添加了以下行,但并未将其突出显示,而是出于我无法理解的原因仅在我的答案中添加评论:“或使用将隐式添加 -lstdc++ 选项的 C++ 编译器,例如 g++。”

于 2015-03-26T17:25:34.317 回答
18

如果由于某种原因没有链接到标准库(嵌入式场景中也可能出现这种情况),则必须提供自己的运算符newdelete. 在最简单的情况下,您可以简单地 wrapmalloc或从您自己喜欢的来源分配内存:

void * operator new(std::size_t n)
{
  void * const p = std::malloc(n);
  // handle p == 0
  return p;
}

void operator delete(void * p) // or delete(void *, std::size_t)
{
  std::free(p);
}

如果您正在为普通的托管平台进行编译,则永远不必这样做,因此如果确实需要这样做,您最好熟悉平台上内存管理的复杂性。

于 2011-08-10T17:53:33.733 回答
10

我只会引用文档,因为他们说得更好。

编写 C++

如果在配置 avr-gcc 期间将 c++ 包含在启用的语言中,则可以用 C++ 为 AVR 平台编写程序。编写 C AVR 程序部分中的几乎所有内容都适用,因此请先阅读。

使用 C++ 的主要缺点是:

C++ calling convention side-effects
No libstdc++ support.

C++ 调用约定副作用

如果需要,某些 C++ 功能会自动生成隐含代码,这会浪费宝贵的程序内存空间和处理器时间。例如,如果在程序中的某个时刻,函数按值传递给 C++ 对象:

void myfunction(MyCppClass object);

您最终会生成一个默认的复制构造函数,并调用它来创建 myfunction() 中使用的对象的临时副本。如果这不是您想要的,请小心:通过传递对常量 MyCppClass 对象的引用应该可以获得等效行为,同时避免代码和执行开销。

缺少 libstdc++ 和其他 C++ 功能

没有任何 C++ 标准模板、类或函数可用。此外,操作符 new 和 delete 尚未实现。

也缺乏 C++ 异常支持。您可能需要确保使用 -fno-exceptions 编译器选项来关闭 C++ 前端中的异常。

有什么作用?即使您习惯使用的许多 C++ 好东西都不可用,但用 C++ 对 AVR 进行编程还是值得的。构造函数和析构函数都是函数式的,使用类和面向对象编程的组织优势可能使 C++ 成为一个不错的选择。

于 2011-08-10T17:58:21.000 回答
5

如果你只是想做一个界面,你不需要 new/delete。只需从基类析构函数中删除“虚拟”,并确保派生类具有 __cxa_pure_virtual() 的实现。

这是一个可编译的示例。(我删除了退货以保持简单,但它适用于它们。)

在 PacketWriter.h 中

class PacketWriter {
public:
    virtual void nextByte() = 0;
protected:
    ~PacketWriter() {}
};

在 StringWriter.h 中

#include "PacketWriter.h"

class StringWriter : public PacketWriter {
public:
    StringWriter(const char* message);
    void nextByte();
};  

在 StringWriter.cpp 中

#include "StringWriter.h"

// Definition of the error function to call if the constructor goes bonkers
extern "C" void __cxa_pure_virtual() { while (1); }

StringWriter::StringWriter(const char* message)
{
    // constructor code here
}

void StringWriter::nextByte()
{
}

编译avr-g++ StringWriter.cpp

于 2012-11-17T01:53:53.330 回答