1

C++およびg++のコンパイルとリンクに関する次のnoobの質問にご協力ください。基本的に、2つの異なるファイルに2つのクラスがあり、それらをコンパイルできますが、リンクしようとすると、両方をリンクしていても、一方のクラスが他方のメソッドを見ることができません。この場合、オブジェクトファイルの順序は役に立ちません。

この問題は、パラメーターを受け取るデフォルト以外のコンストラクターに関連しているようです。

私は次の簡単なコードで問題を抽出して再現しました:

ファイル:a.cpp

#include <iostream>

class A
{
  public:
  int my_int;
    A(int i) {
      my_int = i;
      std::cout << "A";
    }
};

ファイル:a.hpp:

#ifndef __A_H_
#define __A_H_

class A
{
  public:
  A(int i);
};

#endif

ファイルb.cpp:

#include <iostream>

using namespace std;

#include <a.hpp>

class B
{
  public:
  int my_int;
    B(int i) {
      my_int = i;
      A a(i);
      cout << "B\n";
    }
};

int main(int argc, char* argv[])
{
  B b(5);
  cout << "hello world: ";
  cout.flush();
  return 0;
}

ビルドに使用するコマンド:

g++ -c -I. a.cpp
g++ -c -I. b.cpp
g++ -o c_test a.o b.o

あるいは、私はこれらのそれぞれを試しました:

g++ -o c_test b.o a.o
g++ -I. -o c_test a.cpp b.cpp
g++ -I. -o c_test b.cpp a.cpp

上記のリンクシナリオのいずれかで発生するエラー:

b.o: In function `B::B(int)':
b.cpp:(.text._ZN1BC1Ei[B::B(int)]+0x1c): undefined reference to `A::A(int)'
collect2: ld returned 1 exit status

洞察を事前に感謝します。

(これが再投稿の場合は申し訳ありません-私はそれを投稿したと思いましたが、表示されません...)

4

6 に答える 6

3

それはそのようには機能しません。あなたが遭遇したのは技術的にはODR違反です。これは大まかに言ってA、両方a.cppb.cpp同じものでなければならないことを意味します。そうではありません。

さらに、コンストラクターは暗黙的inlineにa.cppにあるため、そのコードを出力する必要はありません。

a.cppに変更

#include <iostream>
#include "a.hpp"

A::A(int i) {
      my_int = i;
      std::cout << "A";
}

エラーを修正します。

于 2011-10-03T13:21:23.100 に答える
1

a.cpp1つの定義規則に違反し、A完全に再定義しています。ソースファイルで関数を定義したいだけです。

A::A(int i) {
  my_int = i;
  std::cout << "A";
}

また、さまざまな不要なコンテキストでsが'intとして扱われないように、関数を明示的にマークすることもできます。A

于 2011-10-03T13:22:19.890 に答える
0

行うべき正しいことは次のとおりです。

a.hpp

#ifndef __A_H_
#define __A_H_

class A
{
  public:
    int my_int;
  A(int i);
};

#endif

a.cpp

#include <iostream>

#include "a.hpp"

A::A(int i) {
      my_int = i;
      std::cout << "A";
    }

b.cpp-同じまま

于 2011-10-03T13:32:15.393 に答える
0

では、コンストラクタを単純にとして定義するa.cpp必要があります。の定義全体を本体のコンストラクターコードで記述することにより、コンストラクターをインライン関数として暗黙的に定義しているため、オブジェクトファイルにコンストラクターの定義がありません。#include "a.hpp"A::A(int i) { ... }class Aclass

于 2011-10-03T13:23:24.470 に答える
0

両方ともと呼ばれる2つの異なるクラス(1つは含むmyint、もう1つは含まない)がありclass Aます。あなたはそれをすることはできません。次のように変更a.cppします。

#include <iostream>
#include "a.hpp"

A::A(int i) {
  my_int = i;
  std::cout << "A";
}

そして、次のように変更a.hppします。

#ifndef __A_H_
#define __A_H_

class A
{
 public:
 int my_int;
 A(int i);
};

#endif

それについて、あなたがそれを持っている方法、誰かがこれをした場合、コンパイラは何をするでしょうか:

#include "a.hpp"
// ...
    A foo(3);
    cout << sizeof(foo) << endl;

class Aコンストラクター以外のメンバーがあることをどうやって知ることができますか?どうやってサイズを知ることができますか?

于 2011-10-03T13:24:23.900 に答える
0

プログラムに2つの別個のAクラスがあるため、単一定義規則に違反しています。A.cppファイルの単純な一般的な実装は次のようになります。

#include "a.h" // where the definition of the type is
A::A( int x ) : myint(i) {}

タイプの適切な定義を含む「ah」の場合:

#ifndef A_H_ // identifiers containing double underscores (__) are reserved, don't use them
#define A_H_
class A
{
  int myint; // This must be present in the definition of the class!
public:
  A(int i);
};
#endif;

そして、Bの実装では、おそらく次のことを意味します。

#include "a.h"     
#include <iostream>

using namespace std;  // I don't like `using`, but if you use it, do it after all includes!
class B {
public:
//   int my_int;      // do you really want to hide A::my_int??
    B(int i) : A(i) { // use the initializer list
      cout << "B\n";
    }
};
于 2011-10-03T13:25:51.780 に答える