29

クラス階層を持ち、そこからオブジェクトをファクトリ内でのみ作成できるようにしたいと考えています。

例:

class Base
{
    protected:
        Base(){};
        virtual void Init(){};

    friend class Factory;
};

class SomeClass : public Base
{
    public://I want protected here! Now it's possible to call new SomeClass from anywhere!
        SomeClass(){};
        void Init(){};
};

class Factory
{
    public:
        template<class T>
        T* Get()
        {
            T* obj = new T();
            obj->Init();

            return obj;
        }
};

int main()
{
    Factory factory;
    SomeClass *obj = factory.Get<SomeClass>();
}

friend class Factory私の問題は、Factory からのみオブジェクトを作成できるようにしたいのですが、Base から派生したすべてのクラスで宣言したくないということです。

派生クラスでフレンドを伝播する方法はありますか? この動作を達成する他の方法はありますか?

4

7 に答える 7

17

いいえ、意図的に不可能です。

カプセル化による問題です。

パスワードを管理するクラス「PswClass」があるとします。これは、他のクラスとのカスケード フレンドです。PswClass から継承した場合:

 class Myclass : public PswClass {
     .......
 }

このようにして、プライベートなフィールドにアクセスできるかもしれません。

于 2012-12-17T15:11:05.130 に答える
4

ここで説明されているように、友情は継承でも推移的でもありません:継承のあるフレンドクラス

少し実験した後、このハックを使用してグローバルコンテナをセットアップする方法 (C++03)? 、オブジェクトを作成するための「工場」固有の権利を与える方法を見つけたと思います。

これは簡単で汚いコードです。(ハックを表示するには、一番下に向かってスクロールします。)

class Object {};

class Factory {
public:
    // factory is a singleton
    // make the constructor, copy constructor and assignment operator private.
    static Factory* Instance() {
        static Factory instance;
        return &instance;
    }

    public: typedef Object* (*CreateObjectCallback)(); 
    private: typedef std::map<int, CreateObjectCallback> CallbackMap; 

public: 
    // Derived classes should use this to register their "create" methods.
    // returns false if registration fails
    bool RegisterObject(int Id, CreateObjectCallback CreateFn) {
        return callbacks_.insert(CallbackMap::value_type(Id, createFn)).second; 
    }

    // as name suggests, creates object of the given Id type
    Object* CreateObject(int Id) {
        CallbackMap::const_iterator i = callbacks_.find(Id); 
        if (i == callbacks_.end()) { 
            throw std::exception(); 
        } 
        // Invoke the creation function 
        return (i->second)(); 
    }

    private: CallbackMap callbacks_; 
};

class Foo : public Object {
    private: Foo() { cout << "foo" << endl; }
    private: static Object* CreateFoo() { return new Foo(); }


public:
    static void RegisterFoo() {
        Factory::Instance()->RegisterObject(0, Foo::CreateFoo);     
    }
};

class Bar : public Object {
    private: Bar() { cout << "bar" << endl; }
    private: static Object* CreateBar() { return new Bar(); }

public:
    static void RegisterBar() {
        Factory::Instance()->RegisterObject(1, Bar::CreateBar);     
    }
};

// use the comma operator hack to register the create methods
int foodummy = (Foo::RegisterFoo(), 0);
int bardummy = (Bar::RegisterBar(), 0);

int main() {
    Factory::Instance()->CreateObject(0); // create foo object
    Factory::Instance()->CreateObject(1); // create bar object
}
于 2012-12-17T15:13:09.547 に答える
2

friendいいえ、基本クラスから宣言を継承する方法はありません。ただし、Baseコンストラクターprivateを作成すると、派生クラスのインスタンスは助けなしでは作成できなくなりFactoryます。

于 2012-12-17T14:58:12.317 に答える
2

他の人が言ったように、友情は継承できません。

これは、「Abstract Factory」パターンの良い候補のようです。

base から派生した「SomeClass」がポリモーフィックに使用されていると仮定します。Base オブジェクトを作成する抽象ファクトリ ベースを宣言します。各コンクリート ファクトリをベースから派生させ、ベース作成メソッドをオーバーライドします...

例については、 http://en.wikipedia.org/wiki/Abstract_factory_patternを参照してください

于 2012-12-17T15:28:18.137 に答える
1

あなたはそれをすることはできません。これは、カプセル化を保護するために行われます。この投稿を参照してください:C ++が継承された友情を許可しないのはなぜですか?

于 2012-12-17T15:00:48.367 に答える
0

今後の参考のために、OP と私の間のチャットから生まれた別のアイデアはfriend、OP が望んでいたように を 1 回だけ使用するだけで機能します。もちろん、これは普遍的な解決策ではありませんが、場合によっては役立つ場合があります。

以下のコードは、本質的なアイデアを示す最小限のものです。Factoryこれは、残りのコードに「統合」する必要があります。

class Factory;

class Top { // dummy class accessible only to Factory
private:
    Top() {}
friend class Factory;
};

class Base {
public:    
    // force all derived classes to accept a Top* during construction
    Base(Top* top) {}  
};

class One : public Base {
public:    
    One(Top* top) : Base(top) {}
};

class Factory {
    Factory() {
        Top top;  // only Factory can create a Top object
        One one(&top);  // the same pointer could be reused for other objects
    }
};
于 2012-12-17T17:31:18.747 に答える