2

ユーザーが一連の線形方程式に対して一連の記号操作を実行できるようにする単純なアプリケーションを作成しようとしており、この目的のために 「Symbolicc ++」ライブラリ(より具体的には最新バージョン 3.35) を使用しています。

私は C++ の経験が少なく、サードパーティのライブラリを実際に使用したことがないため、ライブラリの適切な使用方法を知らず、ばかげた間違いを犯している可能性があります。

問題は、ライブラリのメイン ヘッダーを含む複数のファイルで構成されるプログラムをコンパイル (およびリンク) しようとすると、多数の定義エラーが発生することですエラーは、ライブラリのファイル(私のものではない)で定義されている関数とクラスを参照しています。

非常に単純な例: main.cpphead.hhead.cppというファイルがあるとします。内容は次のとおりです。

main.cpp
------------------
#include <iostream>
#include "head.h"

int main()
{
    return 0;
}

head.h
------------------
#ifndef SOMETHING
#define SOMETHING

#include "symbolicc++.h"

#endif

head.cpp
------------------
#include "head.h"
//nothing

もちろん、実際のプログラムのファイルにはさらに多くのファイルが含まれていますが、これだけでも、たとえば次のようにプログラムをビルドしようとしています。

g++ -I /path to library's header files/ main.cpp head.cpp

次のような何百ものエラーメッセージが表示されます。

/tmp/ccYNzlEF.o: In function `Cloning::Cloning()':
head.cpp:(.text+0x0): multiple definition of `Cloning::Cloning()'
/tmp/ccNWUnnC.o:main.cpp:(.text+0x0): first defined here

たとえば、Cloning::Cloning()は、ライブラリのヘッダー ファイルの 1 つであるcloning.hで宣言されています。

symbolicc++.hを含む1 つのファイルのみを含むプログラムは問題なく動作します。

また、このプロジェクトを Visual Studio 2012 でビルドしようとしましたが、同様の結果が得られました。

残念ながら、この問題に関する情報を見つけることができませんでした。事実上、見つかったすべての資料は、ユーザーが作成したヘッダー ファイルのエラーに関するものでした (他の誰かが作成したライブラリとは対照的に)。

4

1 に答える 1

2

このライブラリはひどく壊れているようです。"symbolicc++.h"設計上、1 つの定義規則に違反しない限り、複数回含めることはできません。

たとえば、 を見てみましょうcloning.hCloningデフォルトのコンストラクター宣言でクラスを定義します。

class Cloning
{
 private: int refcount;
          void (*free_p)(Cloning*);
// ...    
 public:  Cloning();
// ...
};

後で、ヘッダー ファイル内で、そのコンストラクターも定義します。

Cloning::Cloning() : refcount(0), free_p(0) {}

それでおしまい。直接的または間接的にインクルードする *.cpp ファイルはすべてcloning.h、同じ関数の定義に公開されます。リンカーは複数の定義に気づき、あきらめます。

を変更してみてくださいcloning.h。上記のコンストラクター定義行を削除し、コンストラクター定義をクラス定義に配置して、インライン関数にします。

// just to see what's going on...
class Cloning
{
 private: int refcount;
          void (*free_p)(Cloning*);
// ...

 public:  Cloning() : refcount(0), free_p(0) {};
// ...
};

これにより、 のエラーが修正されますCloning::Cloning。しかし、それは問題をより明確にするためのものです。これを行うことはお勧めしません。コードを修正するのはライブラリ作成者の仕事です。

さらに推奨される読み物:ガードを含めるのはなぜ複数の関数定義を防げないのですか?


数行の独自のコードで同じ問題を再現する方法を次に示します。

head.h:

#ifndef SOMETHING
#define SOMETHING

struct Example
{
    Example(); // constructor declaration
};

Example::Example() // constructor definition
{
}

#endif

head.cpp:

#include "head.h"
//nothing

main.cpp:

#include "head.h"

int main()
{
}

リンカ エラーの例 (Visual C++ 2013 から取得):

1>main.obj : error LNK2005: "public: __thiscall Example::Example(void)" (??0Example@@QAE@XZ) already defined in head.obj
1>[...] fatal error LNK1169: one or more multiply defined symbols found

このライブラリを絶対に使用する必要がある場合は、独自の安全なラッパーを構築する必要があります。しかし、率直に言って、そうしないでください。同じ問題を解決し、C++ 言語の規則と規則に従って実際に使用できるライブラリが他にも多数あると確信しています。

于 2015-03-22T16:29:41.400 に答える