ファイル分割の仕方

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
MASSA

ファイル分割の仕方

#1

投稿記事 by MASSA » 14年前

VC++2008を使っています

まだ、C++を学び始めて間もないので、初歩的な質問なんですが…

比較的大きなプログラムだとソースコードを複数のファイルに分割して書きますよね…


その際に

例えばA .cpp とB.cppを作ったとして…

両方のファイルで同じ変数を扱うのには、どのような方法があるのでしょうか…


よろしくお願いいたします

たかぎ
記事: 328
登録日時: 15年前
住所: 大阪
連絡を取る:

Re: ファイル分割の仕方

#2

投稿記事 by たかぎ » 14年前

型Aのオブジェクトaを複数の翻訳単位からアクセスするには、どれかひとつの翻訳単位でaを定義し、他ではexternを付けて宣言します。

コード:

// A.cpp
A a;  // ここでオブジェクトaを定義
...

コード:

// B.cpp
extern A a;  // オブジェクトaの宣言
...
ただし、型Aに明示的なコンストラクタがある場合、あるいは定数式以外の初期化子を持つ場合は初期化の順序が問題になります。
これを回避するには、たとえば次のようにヘッダファイルでインライン関数を定義しておくと便利です。

コード:

// A.hpp
#ifndef A_HPP_
#define A_HPP_

inline A& a()
{
  static A instance;
  return instance;
}

#endif
これで、関数aを呼び出すことで、関数内で定義されている型Aのオブジェクトaにアクセスでき、しかも初期化順序の問題もクリアできます。
なお、デストラクタによる解体の順序まではコントロールできませんので、終了時処理の順序に依存する場合はさらに工夫が必要になります(高難度です)。

アバター
a5ua
記事: 199
登録日時: 15年前

Re: ファイル分割の仕方

#3

投稿記事 by a5ua » 14年前

以下のような、グローバル変数を使うプログラムを例として考えます。

【A.cpp】

コード:

#include <iostream>

// みんなで共有する変数
int shared;

// sharedの値をリセットする関数
void reset()
{
	shared = 9999;
}

int main()
{
	reset();
	std::cout << shared << std::endl;
	shared = 100;
	std::cout << shared << std::endl;
	reset();
	std::cout << shared << std::endl;
}
reset()という関数を別のファイル(B.cpp)に定義したいとしましょう。

【B.cpp】

コード:

// sharedの値をリセットする関数
void reset()
{
	extern int shared;	// sharedという外部変数を使用するという宣言
	
	shared = 9999;
}
外部で定義されている変数を使用するには、externというキーワードをつけて変数を宣言します。
また、このときのA.cppは以下のようになります。

【A.cpp】

コード:

#include <iostream>

// みんなで共有する変数
int shared;

// C++では宣言されていない関数は使えないので、宣言が必要
// 通常これらの宣言は、ヘッダファイルとしてまとめて提供する
void reset();

int main()
{
	reset();
	std::cout << shared << std::endl;
	shared = 100;
	std::cout << shared << std::endl;
	reset();
	std::cout << shared << std::endl;
}
ちなみに、
void reset();
という宣言は、
extern void reset();
を省略したもので、reset();という外部関数を使うという宣言になります。

MASSA

Re: ファイル分割の仕方

#4

投稿記事 by MASSA » 14年前

なるほど!

お二方、ありがとうございます。


ところで、extern宣言を使うと、その変数を検索する処理が入るんですよね?

処理速度への影響はどの程度あるのでしょうか…

YuO
記事: 947
登録日時: 15年前
住所: 東京都世田谷区

Re: ファイル分割の仕方

#5

投稿記事 by YuO » 14年前

MASSA さんが書きました:ところで、extern宣言を使うと、その変数を検索する処理が入るんですよね?
処理速度への影響はどの程度あるのでしょうか…
外部宣言の最終的な解決は,リンカの仕事になります。
なので,リンクの速度への影響はありますが,実行速度への影響はありません。
ただし,物理的なメモリ配置によるキャッシュへの影響から来る実行速度への影響は除きます。
# 同一翻訳単位の定義の方が物理的にまとまって配置されることが多い。

たかぎ
記事: 328
登録日時: 15年前
住所: 大阪
連絡を取る:

Re: ファイル分割の仕方

#6

投稿記事 by たかぎ » 14年前

MASSA さんが書きました:ところで、extern宣言を使うと、その変数を検索する処理が入るんですよね?

処理速度への影響はどの程度あるのでしょうか…
オブジェクトを直接参照する場合は影響ありません。
ただし、私が示した後者の方法(関数を介してアクセスする方法)の場合、若干のオーバーヘッドがあります。
オブジェクトの型によっては後者の方法を使うしかないので、まずはどんな型なのかを明らかにしてください。

MASSA

Re: ファイル分割の仕方

#7

投稿記事 by MASSA » 14年前

なるほど!!

勉強になりました

ありがとうございました。

閉鎖

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