ある 1 つのクラスの複数のメンバを別々のコンパイル単位で定義できる

また、C++ についてのメモです。

C++のリンケージとクラスは,ほぼ直交した概念です. たとえば,メンバ関数は,(アクセス制御の public/private いかんに関わらず) 複数のソースファイルに配置することができます.

http://www.nces.is.nagoya-u.ac.jp/NEXCESS/blog/index.php?itemid=90

たとえば、以下のような、puts_a, puts_b という 2 つのメンバ関数を持つクラスがあったとして、

// sepclass.h

#include <string>
#include <iostream>

class sepclass {
private:
  std::string const a;
  std::string const b;
public:
  sepclass(std::string const a, std::string const b) : a(a), b(b) {}
  void puts_a() const;
  void puts_b() const;
};

これらのメンバの定義を単一のコンパイル単位でまとめて定義してしまわなければいけない、ということはないようです。

// puts_a.cpp

#include "sepclass.h"

void sepclass::puts_a() const {
  std::cout << a;
}
// puts_b.cpp

#include "sepclass.h"

void sepclass::puts_b() const {
  std::cout << b;
}

こんなふうに、バラバラに定義してしまっても、問題なくコンパイルできるし、リンクできます。*1

main はこんな感じで、

// main.cpp

#include "sepclass.h"

int main() {
  sepclass obj("hello", "world");
  obj.puts_a();
  std::cout << ", ";
  obj.puts_b();
  std::cout << "." << std::endl;
  return 0;
}

コンパイル、リンクは普通に、

$ g++ -c puts_a.cpp
$ g++ -c puts_b.cpp
$ g++ -c main.cpp
$ g++ puts_a.o puts_b.o main.o -o sepclass

さらに、ヘッダファイルで宣言したメンバが未定義でも、どこでも使用されてなければ問題はおこらないようです。*2

このように,クラスのスコープとは別に,メンバを自由に様々なソースファイルに分散させてしまうことができます. しかしながら,可読性と扱い易さのためには,メンバ関数を分散させるべきではありません.

http://www.nces.is.nagoya-u.ac.jp/NEXCESS/blog/index.php?itemid=90

ということですが、まぁ分けて書きたい事情があったのでした。

2009-05-21

ちょっと修正。

*1:オブジェクトファイルになってしまえばクラスとか関係ねー、ってことですかね?

*2:ソースコードがそんな状態になってること自体が問題という気もしますが