web-dev-qa-db-ja.com

クラスヘッダーファイルでのプライベート関数の宣言の回避(C ++)

(C++の場合)構造がヘッダーファイルで宣言されているクラスがあります。そのヘッダーファイルは多くのソースファイルに含まれているため、編集するときに多くのファイルを再コンパイルする必要があります。

このクラスには、1つのソースファイルでのみ呼び出される一連のプライベート関数があります。現在、それらはヘッダーファイルのクラス構造で宣言されています。したがって、このタイプの新しい関数を追加したり、引数を編集したりすると、多くのファイルが再コンパイルされます。関数を定義して呼び出すファイルだけが再コンパイルされるように、関数を別の場所で宣言したいと思います(時間を節約するため)。ただし、内部クラス変数にアクセスできる必要があります。

どうすればこれを達成できますか?

23
user664303

メインクラス宣言の外でクラスのメンバー関数を宣言する方法はありません。したがって、問題のクラスの外部で、クラスの特定のインスタンスのメンバー変数にアクセスできる関数を宣言したい場合は、そのインスタンスを関数に渡す以外に方法はありません。さらに、関数がプライベート変数と保護された変数にアクセスできるようにする場合は、それらを新しいクラスに配置し、元のクラスをそのフレンドにする必要があります。例えば。

header.h:

class FooImpl;

class Foo {
public:
   int bar();
   friend class FooImpl;
private:
   int var;
}

impl.cpp:

#include "header.h"

class FooImpl {
public:
   int bar(Foo &);
}

int FooImpl::bar(Foo &foo) {
return foo.var;
}

int Foo::bar() {
return FooImpl::bar(*this);
}
4
user664303

pImplイディオム を使用します-可視クラスはrealクラスへのポインターを保持し、呼び出しをパブリックメンバー関数に転送します。

編集:コメントに応えて

// Foo.h:

class FooImpl; // Do *not* include FooImpl.h
class Foo {
public:
  Foo();
  ~Foo();
  //.. also need copy ctor and op=
  int bar();
private:
  FooImpl * Impl;
};

// FooImpl.h:

class FooImpl {
public:
  int bar() { return Bar; }
private:
  int Bar;
};

// Foo.cpp:

#include "FooImpl.h"

Foo::Foo() { Impl = new FooImpl(); }
Foo::~Foo() { delete Impl; }
int Foo::bar() { return Impl->bar(); }

クラスの実際の実装をFooImplに保持します--Fooには、FooImplそして単にこれらに呼び出しを転送します。すべてのユーザーには「Foo.h」のみが含まれます。FooImplのユーザーに変更が表示されることなく、Fooのすべての非公開の詳細を変更できます。

14
Erik

お探しですか コンパイラファイアウォール 、別名PIMPL?

2

パブリック関数のみを含む抽象基本クラスを作成し、ヘッダーでこれを参照します。実クラスを別の場所の実装として作成します。クラスを作成する必要があるソースファイルのみが、実装クラスヘッダーを確認する必要があります。

1
Neil Kirk