2017-12-09 7 views
0

私がしようとしていることを正確に指定しておきたいのですが、foo-barプログラムをmain、foo.h、foo.cpp、bar.hの5つのファイルに分割する必要があります。 、bar.cpp。私のヘッダーファイル(foo.hとbar.h)は対応するクラスの宣言を含んでいますが、C++ファイル(foo.cppとbar.cpp)はクラスを定義するためのものです。C++ソースファイルを複数のファイルに分割する際のトラブル

私はVisual Studioを使用しています。これまでのところ、赤い旗を表示していた唯一のファイルは私のメインファイルです。ここに私のコードは、これまでのところで、私は私のメインのファイルにスローされるエラーが含まれます:

main.cppに

#include <iostream> 
#include "foo.h" 
#include "foo.cpp" 
#include "bar.h" 
#include "bar.cpp" 
using namespace std; 

int main() { 
    Bar b(25); /*I am getting a red flag under the 25, stating there is no constructor that can convert int to Bar*/ 

    b.func1(); /*I'm getting a red flag under func1 and func2 stating neither of them are members of Bar*/ 
    b.func2(34); 

    return 0;} 

がfoo.h

#ifndef foo_h 
#define foo_h 
#include "foo.cpp" 
class Foo {}; 
#endif 

FOO .cpp

#ifndef foo_c 
#define foo_c 

#include "foo.h" 
#include "bar.cpp" 
private: 
    int data; 
public: 
Foo(int d) : data(d) {} 

int get_data() { return data; } 

virtual void func1() = 0; 

virtual int func2(int d) = 0; 


#endif 

bar.h

#ifndef bar_h 
#define bar_h 
#include "bar.cpp" 
#include "foo.h" 
class Bar : public Foo {}; 
#endif 

bar.cpp

#ifndef bar_c 
#define bar_c 

#include "bar.h" 
#include "foo.h" 
#include "foo.cpp" 

Bar(int d) : Foo(d) {} 

void func1() { 
    cout << "Inside func1\n"; 
    cout << "\tData is " << get_data() << endl; 
} 

int func2(int d) { 
    cout << "Inside func2 with " << d << endl; 
    cout << "\tData is " << get_data() << endl; 
    return d; 
} 

#endif 

私はそれを分割するまで、私のプログラムが働いていたが、今では私はそれをコンパイルしようとする私にこのメッセージを投げ続け、赤旗のカップルがあります私のメインコードで。このコンソールは、私に語ったものです:

んが、適切なコンストラクタが

関数func1を棒にint型に変換するために存在していないが、クラスバー

関数func2のメンバーは、クラスのバー

のメンバーではありませんされていません

私の質問は何ですか:私は間違っています、そして、私がやろうとしていることについて行く良い方法がありますか?

ありがとうございます。

+1

あなたのcppファイルのみ.hファイルを含める必要はありません。ただし、.cppファイルをコンパイルし、オブジェクトファイルがリンクステージで使用可能であることを確認する必要があります。それがコンパイル単位と呼ばれる理由です。 –

+0

cppファイルはインクルードする必要がないので、 '#ifndef'マクロブロックは必要ありません。 –

答えて

1

あなたは決して#include.cppファイルではありません。代わりに、各.cppファイルをオブジェクトファイルにコンパイルし、それらを実行可能ファイルにリンクします。

プリプロセッサ段階では、コンパイラはすべて#include d個のファイルを取り、それらを1つの大きなプログラムに連結したものとして扱います。場合によっては、特定のファイルが#include d回複数回表示されることがあります。ヘッダーファイルの宣言は繰り返されるかもしれませんが、ソースファイルからの複数の定義はエラーを引き起こします。

オブジェクトファイルを作成するとき、ヘッダーファイルは名前と型をチェックするためにコンパイラによって使用されますが、実際の定義は必要ありません(このガードはソースファイルにインクルードガードを使用しているためです)。 の定義はで、オブジェクトファイルにコンパイルされています。別々のオブジェクトファイルの目的は、これらの定義のコンパイルをモジュール単位で分離することです。

1

このコードには複数の誤解があります。おそらく、個別に記述して議論するよりも、それらを完全に修正する方が簡単かもしれません。

まず、依存関係ツリーの一番下から始めましょう。下に仮想クラスFooがあります。正しい宣言がここにあります。

#ifndef foo_h 
#define foo_h 
class Foo { 
private: 
    int data; 
public: 
    Foo(int); 
    int get_data(); 
    virtual void func1() = 0; 
    virtual int func2(int) = 0; 
}; 

#endif 

ヘッダーファイルには、すべてのメソッドの宣言が含まれています。しかし、非仮想メソッドの実装はfoo.cppファイルに移動されます。私たちは私たちが今までそれを含めるつもりはありませんので、.cppファイルの複数回のインクルードから保護するために特別な機器を必要としない

#include "foo.h" 

Foo::Foo(int d) : data(d) { } 

int Foo::get_data() { return data; } 

注意。

今すぐFooは、私たちのためにいくつかの実際の仕事を行うクラスBarの親です。もう一度、すべてのメソッドがクラス宣言内で宣言されます。

#ifndef bar_h 
#define bar_h 
#include "foo.h" 
class Bar : public Foo { 
public: 
    Bar(int); 
    void func1(); 
    int func2(int); 
}; 
#endif 

そしてその実装はbar.cppと呼ばれる対応するコンパイル単位にあります。クラスメソッドを実装する場合、メソッド名にクラス名を付加することによって、メソッドがどのクラスに属するかを示します。 Bar::func1

#include "bar.h" 
#include "foo.h" 

#include <iostream> 

Bar::Bar(int d) : Foo(d) {}; 

using namespace std; 

void Bar::func1() { 
    cout << "Inside func1\n"; 
    cout << "\tData is " << get_data() << endl; 
} 

int Bar::func2(int d) { 
    cout << "Inside func2 with " << d << endl; 
    cout << "\tData is " << get_data() << endl; 
    return d; 
} 

最後に、わずかな変更が必要なmain.cppで使用します。

#include <iostream> 
#include "foo.h" 
#include "bar.h" 
using namespace std; 

int main() { 
    Bar b(25); 

    b.func1(); 
    b.func2(34); 

    return 0;} 

ここでプロジェクトを構築しましょう。 GCCを使用していた場合、一連のCLIコマンドとして記述するのは簡単でした。 Visual Studioを使用しているので、GUIを使用して対応するアクションを実行する必要があります。

  1. まずフー

    g++ -c -Wall foo.cpp

  2. 次はコンパイルバー

    g++ -c -Wall bar.cpp

  3. をコンパイルコンパイルメイン

    g++ -c -Wall main.cpp

  4. はついにそれを実行し、一緒

    g++ -o main foo.o bar.o main.o

  5. それをすべてリンクして出来上がり

 
    Inside func1 
     Data is 25 
    Inside func2 with 34 
     Data is 25 
+1

OPはVisual Studioを使用していますが、 'g ++'ではなく... –

+0

ありがとうございました。私はVSを使用しているので、私がしなければならなかったのはデバッガを実行して、すべてをまとめてコンパイルしたものです。ちょうどコードを投げるのではなく、あなたの修正を説明することに本当に感謝します。 – B1azingPh03nix

関連する問題