2

2 つのクラス実装があります ( .cpp files)

headerどちらも(.h) ファイルに実装された関数が必要です。どちらの .cpp ファイルにも .h ファイルが含まれています。コンパイル後、2 つのファイルは 2 つの.cppファイルになり.oます。

2 つのオブジェクト ファイルをリンクするときに、関数が 2 回定義されていませんか?

#ifndefこの状況を防ぐことはできますか?

使用#ifndefしましたが、次のメッセージが表示されました。

ld: 1 duplicate symbol for architecture x86_64
4

2 に答える 2

5

関数宣言(特定の名前とシグネチャを持つ関数が存在するというステートメント) と関数定義(関数が実際に何をするかを決定するコード)の違いを理解する必要があります。

ヘッダーで関数を定義すると、関数は各オブジェクト ファイルで定義され、それらをリンクしようとすると競合が発生します。#ifndefはこの問題を解決しません。

関数をヘッダーで宣言し、ソース ファイルで定義する場合 (オブジェクトにコンパイルし、それを使用するオブジェクトとリンクする必要があります)、このような問題はありません。この単純なケースで#ifndefは、必要ありません。

たとえば、関数は次のfooように宣言できますfoo.h

int foo(int);

で定義されていfoo.cppます:

int foo(int n)
{
  return(n+3);
}

#ifndefマクロは別の問題を解決します。

于 2013-04-25T02:38:47.577 に答える
2

ベータ版の回答の代わりに、キーワードを使用して、複数の翻訳単位に含まれるヘッダー ファイル内にフリー関数を定義できます。inlineこのことを考慮:

// Foo.h

int foo(){return 1;}

// UsesFoo1.cpp

#include "Foo.h"
int usesFoo2(){return foo();}

// UsesFoo2.cpp

#include "Foo.h"
int usesFoo1(){return foo();}

// Main.cpp

#include <iostream>
int usesFoo1();
int usesFoo2();

int main()
{
   std::cout << usesFoo1() + usesFoo2() << std::endl;
}

int foo()は 2 つの別個の翻訳単位で定義されているため、リンカー エラーが発生します。inlineただし、ここにキーワードを追加してもエラーは発生しません。

// Foo.h

inline int foo(){return 1;}

注: クラス定義内で定義された関数は暗黙的にinlineキーワードを持っているため、そこで省略できます。

于 2013-04-25T03:15:51.580 に答える