2017-01-10 11 views
-2

Я хочу предотвратить что-либо, кроме фабрики для моего класса, от создания объектов типа моего класса. Мне нужен этот класс для публичного интерфейса, но я хочу ограничить его создание только его фабрикой. Как мне это сделать?Как ограничить вызов конструктора одного класса только его заводским классом?

Назовем класс 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. Вам нужно будет определить новый класс утилиты, который можно использовать только по желаемому методу, а затем использовать этот класс для каждого метода, который вы хотите защитить. Я лично считаю этот подход неуклюжим, но он работает.

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{}); 
} 

Только CarFactory можно построить Car, потому что никто другой не может сделать Car::t_private, так как это конструктор является частным. CarFactory не могут получить доступ к частным лицам Car, так как это не друг.

+0

Я разорван, потому что это интуитивно и полезно, но не ограничение, о котором я спрашивал (что может быть невозможно). Я хотел знать, есть ли способ сделать доступным только конструктор Car to CarFactory. Это делает всех частных членов Car доступными для CarFactory :: makeCar(). – tylerjw

+0

@tylerjw См. Отредактированный ответ. –

+1

@tylerjw Я бы пошел с выше, но ... Вставьте еще один слой абстракции. «Автомобиль» - друг «CarFirewall».'CarFirewall' содержит только один метод, который вызывает конструктор' Car'. 'CarFirewall' является другом' CarFactory' ... ОК. Неважно. Франсуа Андри очень много сделал. – 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

Это неинтуитивно, это хороший способ скрыть все реализации и позволить пользователям видеть только интерфейсы. В целом считается хорошей практикой. Это имеет хорошее преимущество в том, что вы не используете отношения друзей (что во многих отношениях проблематично). –

 Смежные вопросы

  • Нет связанных вопросов^_^