ページ 11

クラスを分割コンパイルするには

Posted: 2011年1月25日(火) 21:03
by taketoshi
こんばんわ、お世話になります。
CからC++への勉強を進めている段階で、クラスの分割コンパイルについて不明な点があるので質問させていただきます。
試しに次のようなプログラムを書いてみました。

コード:

//main.cpp
#include "stdafx.h"
#include"class.h"
int _tmain(int argc, _TCHAR* argv[])
{
	test a;
	a.show();
	return 0;
}

コード:

//class.h
class test{
	int a;
	int b;
public:
	test();
	int show();
};
test::test(){
	a = 10;
	b = 20;
};
int test::show(){
	printf("a = %d,b = %d",a,b);
	return 0;
}
上記のコードでmain.cppからクラスを呼び出す事が出来たのですが、此処からが質問になります。
更に、もう一つ.cppファイルを増やして、そこにclass.hをインクルードし、コンパイルした際に

1>test2.obj : error LNK2005: "public: __thiscall test::test(void)" (??0test@@QAE@XZ) は既に クラスの分割.obj で定義されています。
1>test2.obj : error LNK2005: "public: int __thiscall test::show(void)" (?show@test@@QAEHXZ) は既に クラスの分割.obj で定義されています。
1>D:\Windowsプログラミング\クラスの分割\Debug\クラスの分割.exe : fatal error LNK1169: 1 つ以上の複数回定義されているシンボルが見つかりました。

多重定義のエラーが出てしまいます。
どこのcppファイルからもクラスを参照できるようにするにはどの様にしたらいいのでしょうか。
勉強を始めたばかりでトンチンカンなことをたずねているかも知れませんが、よろしくお願いします。

Re: クラスを分割コンパイルするには

Posted: 2011年1月25日(火) 21:29
by softya(ソフト屋)
class.h内で実体を定義してしまっていますので、

コード:

test::test(){
    a = 10;
    b = 20;
};
int test::show(){
    printf("a = %d,b = %d",a,b);
    return 0;
}
を新規にclass.cppを作ってそこに持って行って、これもコンパイル対象としてください。
基本的なことは、C言語と変わりませんよ。

Re: クラスを分割コンパイルするには

Posted: 2011年1月25日(火) 21:33
by maru
関数の定義をヘッダファイルに書いてはいけないことはC言語でも同じです。
どうしてもヘッダファイルに書きたい場合はinline をつけるか、クラスの定義に宣言と同時に定義してしまうことです。
普通は関数はcppファイルに書きます。

コード:

// test.h
class Test
{
private:
  int a, b;
public:
  //コンストラクタ
  Test() : a(10), b(20) {};// クラス定義内で関数を定義
  Test(int a_, int b_) ; // 引数付コンストラクタの宣言
  int show();
};
// 引数付コンストラクタをヘッダファイルで関数を定義
inline Test::Test(int a_, int b_)
: a(a_), b(b_)
{
}
// Test.cpp
#include <iostream>
int test::show(){
    std::cout << "a = " << a <<",b = " << b << std::endl;
    return 0;
}

Re: クラスを分割コンパイルするには

Posted: 2011年1月25日(火) 22:04
by taketoshi
お二方素早いお返事ありがとうございます、出来ました。
分割コンパイルをするまで、クラス定義とメンバ関数は全部ひっくるめてクラスなんだと思い込んでおりました。
クラスの定義だけをヘッダファイルに書けばいいんですね。勉強になりました。

以下のようにコードを書き起こして希望の動作になることを確認しました。
ありがとうございます。

コード:

//main.cpp
#include "stdafx.h"
#include"class.h"
int showsub();//外部関数のプロトタイプ

int _tmain(int argc, _TCHAR* argv[])
{
	test a;
	a.show();
	showsub();//外部関数呼び出し
	return 0;
}

コード:

//sub.cpp
#include "stdafx.h"
#include"class.h"

//クラスのメンバ関数の定義
test::test(){
	a = 10;
	b = 20;
};

int test::show(){
	printf("a = %d,b = %d",a,b);
	return 0;
}

//main関数とは別のオブジェクトを生成する関数
int showsub()
{
	test b;
	b.show();
	return 0;
}

コード:

//class.h
class test{
	int a;
	int b;
public:
	test();
	int show();
};