2016-08-22 12 views
10

埋め込みデバイス用のC++プログラムを作成しています。libstdC++、例外、および動的メモリ割り当てなしでコンパイルしたいと考えています。削除演算子を使用せずにC++をコンパイルする

プログラム例:

#include <stdio.h> 

class A 
{ 
public: 
    virtual ~A() {} 
    virtual void Foo() = 0; 
}; 

class B : public A 
{ 
public: 
    virtual ~B() {} 
    virtual void Foo() override{} 
}; 

int main() 
{ 
    B b; 
    return 0; 
} 

すぐに私は次のエラーに走りました。

$ gcc src.cpp -static -fno-rtti -fno-exceptions -std=c++11

/tmp/ccd0Wydq.o: In function A::~A()': src.cpp:(.text._ZN1AD2Ev[_ZN1AD5Ev]+0x29): undefined reference to operator delete(void*)' /tmp/ccd0Wydq.o: In function A::~A()': src.cpp:(.text._ZN1AD0Ev[_ZN1AD5Ev]+0x20): undefined reference to operator delete(void*)' /tmp/ccd0Wydq.o: In function B::~B()': src.cpp:(.text._ZN1BD2Ev[_ZN1BD5Ev]+0x35): undefined reference to operator delete(void*)' /tmp/ccd0Wydq.o: In function B::~B()': src.cpp:(.text._ZN1BD0Ev[_ZN1BD5Ev]+0x20): undefined reference to operator delete(void*)' /tmp/ccd0Wydq.o:(.rodata._ZTV1A[_ZTV1A]+0x20): undefined reference to `__cxa_pure_virtual' collect2: error: ld returned 1 exit status Makefile:2: recipe for target 'all' failed make: *** [all] Error 1

私は__cxa_pure_virtualが必要な理由を理解するが、私はdelete実装を必要とする理由は私の人生のために得ることができませんでした。

コード内でnewまたはdelete操作を実行しない理由は何ですか?

リンカの要求を満たすために両方の関数を実装すると、どちらも呼び出されていないように見えます(期待どおり)。

これらの機能を実装する方法はありますか?

+0

何もしないことで実装するのに問題がありますか? –

+0

私はそれらが呼び出されていないことを確かめるために大きなassert(1 == 0)でそれらをスタブします。 –

+0

これは醜い解決策です。それが唯一の解決策であれば、私はそれをしますが、なぜそれが事実であるかを知りたいのです。 –

答えて

12

delete式で仮想デストラクタを呼び出すと、呼び出されるoperator deleteは、最も派生したクラスのスコープから決定されます。例えば、

#include <iostream> 

class Base { 
public: 
    virtual ~Base() {} 
}; 

void destroy_base(Base* b) { delete b; } 

class Derived : public Base { 
public: 
    static void operator delete(void* ptr) { 
     std::cout << "Derived::operator delete\n"; 
     ::operator delete(ptr); 
    } 
}; 

int main() { 
    destroy_base(new Derived); 
} 

プリント"Derived::operator delete"、機能destroy_baseクラスDerivedの知識を持たないにもかかわらず。

g ++は、すべてのクラスのvtableに2つのバージョンのデストラクタを入れて実装しています。つまり、メンバとベースだけを破壊するものと、それをすべて行い、適切なoperator deleteを呼び出します。これはあなたの未定義の記号がどこから来ているかです。

delete式を実際に使用しない場合は、::operator delete関数を除外するだけで問題ありません。

+0

コンパイラが2番目のデストラクタを生成しないようにする方法はありますか?私は削除演算子をスタブに興味がありません。 –

+0

私はそう信じません。 – aschepler

+1

@GiladNaamanは、それが可能である方法を想像することはできません。標準では、適切な削除が呼び出されなければならず、ベースクラスのコンパイル時にコンパイラはどのように使用されるかわからないため、演算子deleteを呼び出すデストラクタを生成する必要があります。 – SergeyA

関連する問題