11

次のことを達成することは、どういうわけか可能ですか?

x.hpp-このファイルは他の多くのクラスに含まれています

class x_impl; //forward declare
class x {
    public:
        //methods...
    private:
        x_impl* impl_;
};

x.cpp-実装

#include <conrete_x>
typedef concrete_x x_impl;    //obviously this doesn't work
//implementation of methods...

したがって、基本的には、ユーザーにファイルx.hppを含めてもらいたいのですが、conrete_x.hppヘッダーには注意してください。

私はconcrete_xポインタでしか使用できず、プライベートデータメンバーとしてのみ表示されるため、コンパイラが準備するスペースの量を知るには、前方宣言で十分です。よく知られている「pimplイディオム」によく似ています。

これを手伝ってくれませんか。

PS。void*を使ってキャストしたくない。

4

4 に答える 4

9

実際には、ユーザーから完全に隠すことも可能です。

// Foo.hpp
class Foo {
public:

    //...

private:
    struct Impl;
    Impl* _impl;
};

// Foo.cpp
struct Foo::Impl {
    // stuff
};

私はあなたにそれを思い出させたいと思います:

  • 適切なデストラクタを作成する必要があります
  • したがって、適切なコピーコンストラクター、コピー代入演算子、ムーブコンストラクター、およびムーブ代入演算子も必要になります。

黒魔術を犠牲にして、PIMPLを自動化する方法があります(これと同様std::shared_ptrです)。

于 2012-11-06T18:53:33.360 に答える
5

@Angewからの回答の代わりに、concrete_xクラスxのユーザーに名前を知らせてはならない場合は、次のようにすることができます。

x.hpp

class x_impl;
class x {
  public:
    x();
    ~x();
    //methods...
  private:
    x_impl* impl_;
};

x.cpp

#include <concrete_x>
class x_impl : public concrete_x { };

x:x() : impl_(new x_impl) {}
x:~x() { delete impl_; }
于 2012-11-06T18:20:12.350 に答える
2

これは、前方宣言がクラスの実際の名前を宣言している場合にのみ機能します。したがって、x.hppを次のように変更します。

class concrete_x;
class x {
    public:
        //methods...
    private:
        concrete_x* impl_;
};

x_implまたは、ヘッダーで定義されているクラスの名前を使用し<concrete_x>ます。

于 2012-11-06T17:55:14.737 に答える
0

それがインターフェースの目的です。共有ヘッダーファイルでインターフェイス(純粋な仮想クラス)を定義し、それをユーザーに提供します。インターフェイスから具象クラスを継承し、非共有ヘッダーファイルに配置します。cppファイルに具象クラスを実装します(cpp内に具象クラスを定義することもできます)。

于 2012-11-06T17:57:25.607 に答える