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

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
taketoshi
記事: 221
登録日時: 9年前
住所: 日本国

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

#1

投稿記事 by taketoshi » 9年前

こんばんわ、お世話になります。
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ファイルからもクラスを参照できるようにするにはどの様にしたらいいのでしょうか。
勉強を始めたばかりでトンチンカンなことをたずねているかも知れませんが、よろしくお願いします。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

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

#2

投稿記事 by softya(ソフト屋) » 9年前

class.h内で実体を定義してしまっていますので、

コード:

test::test(){
    a = 10;
    b = 20;
};
int test::show(){
    printf("a = %d,b = %d",a,b);
    return 0;
}
を新規にclass.cppを作ってそこに持って行って、これもコンパイル対象としてください。
基本的なことは、C言語と変わりませんよ。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

maru
記事: 150
登録日時: 9年前

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

#3

投稿記事 by maru » 9年前

関数の定義をヘッダファイルに書いてはいけないことは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;
}
最後に編集したユーザー maru on 2011年1月26日(水) 10:51 [ 編集 1 回目 ]

taketoshi
記事: 221
登録日時: 9年前
住所: 日本国

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

#4

投稿記事 by taketoshi » 9年前

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

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

コード:

//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();
};

閉鎖

“C言語何でも質問掲示板” へ戻る