2017-01-10 10 views
-2

私のクラスのファクトリ以外のクラスの型を構築することを避けたい。私はそのクラスをパブリック・インターフェースにする必要がありますが、その作成をその工場だけに制限したいと考えています。それ、どうやったら出来るの?1つのクラスのコンストラクタの呼び出しを、そのファクトリクラスのみに制限するにはどうすればよいですか?

クラスCarと工場CarFactoryとしましょう。ここでfriendを使用して工場出荷時にすべてのプライベートメンバーを公開することなくこれを行う方法の私の最初のアイデアは、次のとおりです。

class Car { 
private: 
    Car(); 
    Car(Car& ref); 

    friend class CarFactory; 
}; 

class CarFactory { 
public: 
    Car * makeCar(); 
}; 

私は、Javaのための関連する質問が見つかりました:How do I make a constructor available to only the factory class?

あるとして上記のコードは動作します。明確にするために、コンストラクタだけを工場と共有する方法があるのか​​、すべてのプライベートメンバーではないのかを知りたいですか?

+0

これはほとんど動作します。期待され観察された行動とは何か? –

+4

ステートメントの最後に疑問符を置くだけで、役に立つ質問は出ませんか? –

+0

これはそのまま動作しますが、ファクトリクラスのみへのアクセスを制限する正しい方法であるかどうかは不明でした。 CarクラスのすべてのプライベートメンバーをCarFactoryクラスに公開せずにこれを行う方法はありますか? – tylerjw

答えて

3

あなたのコメントから、私はあなたが友人の機能を探していると仮定します。友人の宣告に関するヘルプはhereで見つけることができます。あなたの例が変更されました。

// Forward declare car 
class Car; 

class CarFactory { 
public: 
    Car * makeCar(); 
    Car * makeTruck(); 
}; 

class Car { 
private: 
    Car(); 
    Car(Car& ref); 

    friend Car * CarFactory::makeCar(); 
}; 

Car * CarFactory::makeCar() { 
    return new Car(); 
} 

Car * CarFactory::makeTruck() { 
    return new Car(); // Fails to compile 
} 

編集:あなたが唯一の車のコンストラクタは、工場出荷時に利用できるソリューションのコメントで尋ねました。必要なメソッドでのみ使用可能な新しいユーティリティクラスを定義し、保護したいメソッドごとにそのクラスを使用する必要があります。私は個人的にはこのアプローチが厄介であると思っていますが、うまくいきます。それのコンストラクタがプライベートであるため、誰もがCar::t_privateを作ることはできませんので

class Car { 

public: 
    struct t_private{ 
    private: 
     t_private() = default; 
     friend Car * CarFactory::makeCar(); 
    }; 

    Car(t_private); 

private: 
    Car(Car& ref); 
}; 

Car * CarFactory::makeCar() { 
    return new Car(Car::t_private{}); 
} 

のみ CarFactoryCarを構築することができます。 CarFactoryは、友人ではないので、 Carのプライベートメンバーにアクセスすることはできません。

+0

これは直感的で便利なので私は引き裂かれていますが、私が尋ねた制限はありません(これは不可能かもしれません)。 CarFactoryのコンストラクタを利用できるようにする方法があるかどうかを知りたかったのです。これにより、CarのすべてのプライベートメンバーがCarFactory :: makeCar()に利用可能になります。 – tylerjw

+0

@tylerjw編集された答えをご覧ください。 –

+1

@tylerjw私は上記と一緒に行くだろうが、...抽象化の別のレイヤーを挿入します。 'Car'は' CarFirewall'の友人です。'CarFirewall'には' Car'コンストラクタを呼び出すメソッドが1つしかありません。 'CarFirewall'は' CarFactory'の友人です... OK。気にしないで。 FrançoisAndrieuxはちょうどこれをかなりしました。 – user4581301

-1

Car抽象クラスを作成し、その後、プライベートクラスとして工場内でそれを実装しています

class Car { 
    public: 
    virtual void drive()=0; 
}; 
class CarFactory { 
    private: 
    class CarImp : public Car { 
     ... 
    }; 
    public: 
    Car *makeCar() { return new CarImp(); } 
} 
+0

これは技術的に正しいものですが、私は工場に非公開の実装にコンストラクタを配置することによって尋ねるように正しく動作しませんが、直感的ではありません。抽象的なオブジェクトを構築することができず、ファクトリのプライベートメンバとしてサブクラス化するという副作用を使用しています。 – tylerjw

+0

これは直感的ではありません。これは、すべての実装を非表示にし、ユーザーにインターフェイスのみを表示させるための良い方法です。一般的には良い方法と考えられます。友人関係を使用しないという利点があります(多くの点で問題があります)。 –

関連する問題