0

私はクロスプラットフォームのクラス階層を書いており、プラットフォームに依存する実装を独自のクラスに保持したいと考えています ( #ifdefs. これは私がこれまでに持っているものですが、コンパイラBaseDefは非公開であると不平を言っています。コンパイル中にこの基本構造を維持する方法についての助けをいただければ幸いです:-)

編集:ここから、これは不可能であるように思われます。この一般的な構造を維持してコンパイルできる他の方法はありますか?

ルート.h

class Root {
    private:
        class BaseDef {
            virtual void foo() = 0;
            virtual void bar() = 0;
        };

        #ifdef _WIN32
        class WinImp;
        #else
        class NixImp;
        #endif

        BaseDef* imp;

        BaseDef* getImp();

    public:
        Root() : imp(getImp()) {}
        void foo();
        void bar();
};

ルート.cpp

#include "Root.h"
void Root::foo() {
    imp->foo();
}

void Root::bar() {
    imp->bar();
}

WinImp.h

#ifdef _WIN32
#include "Root.h"
class WinImp : public Root::BaseDef {
    public:
        void foo();
        void bar();
};
#endif

WinImp.cpp

#include "WinImp.h"
#ifdef _WIN32
    Root::WinImp::foo() {

    }

    Root::WinImp::bar() {

    }

    Root::BaseDef* Root::getImp() {
        return new Root::WinImp();
    }
#endif
4

2 に答える 2

1

あなたの主な問題はそれBaseDefが私的なことです。つまり、他のクラス(Root自体を除く)はBaseDef名前にアクセスできません。1つの方法は、BaseDef公開することです。または、の派生クラス(WinImpおよびNixImp)を友達にRootして、名前にアクセスできるようにすることもできますBaseDef。さらにRoot、のメンバーにアクセスできないため、メンバーをBaseDef公開するかRoot、の友達にする必要がありBaseDefます。

class Root {
private:
  class BaseDef {
  public:
    // These need to be public so that Root can see them or Root needs to be a friend. 
    //Nothing else can see BaseDef though so this is safe.
    virtual void foo() = 0;
    virtual void bar() = 0;
  };

  class WinImp; // Forward declare the classes
  friend class WinImp; // And then make them friends
  class NixImp;
  friend class NixImp;

  BaseDef* imp;

  BaseDef* getImp();

public:
  Root() : imp(getImp()) {}
  void foo();
  void bar();
};

void Root::foo() {
  imp->foo();
}

void Root::bar() {
  imp->bar();
}

// Since this is a nested class i made it Root::WinImp
class Root::WinImp : public Root::BaseDef {
public:
  void foo();
  void bar();
};

void Root::WinImp::foo() {}

void Root::WinImp::bar() {}

Root::BaseDef* Root::getImp() {
  return new WinImp();
}

このメソッドは、2003標準(11.4.p2)では許可されていませんが、C ++ 11(同じ例)では明示的に許可されています(11.3.p2)。ただし、clang(3.1テスト済み)は2003モードでもこれを受け入れます。gcc(4.7.2テスト済み)は、派生クラスが同じクラス内にネストされているが、クラス外にネストされていない限り、これを受け入れます(2003モードでも)。

于 2013-01-25T03:22:30.867 に答える
1

それBaseDefは不平を言っていprivateます...

class Root {
    private:
        class BaseDef {
            virtual void foo() = 0;
            virtual void bar() = 0;
        };

だからそれを公開する...

class Root {
    public:
        class BaseDef {
            virtual void foo() = 0;
            virtual void bar() = 0;
        };

脚注:

あなたは避けようとしている#ifdefので、これを取り除いてください:

#ifdef _WIN32
class WinImp;
#else
class NixImp;
#endif

代わりに、単一のクラスを使用してください。

class Imp;
于 2013-01-25T02:25:16.237 に答える