2017-01-10 1 views
-2

내 클래스의 팩토리가 내 클래스의 유형의 객체를 생성하는 것을 막고 싶습니다. 공용 인터페이스를 갖기 위해 클래스가 필요하지만, 팩토리 생성을 팩토리로만 제한하려고합니다. 어떻게해야합니까?한 클래스의 생성자를 해당 팩토리 클래스로만 호출하는 것을 어떻게 제한합니까?

클래스 Car 및 공장 CarFactory을 호출하겠습니다. 다음은이 작업을 수행하는 방법에 내 초기 아이디어는 friend을 사용하고 공장의 모든 private 멤버를 노출하지 않고 있습니다 : How do I make a constructor available to only the factory class?

위의 코드는 그대로 작동합니다

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

    friend class CarFactory; 
}; 

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

내가 자바에 대한 관련 질문을 발견했다. 명확히하기 위해 모든 개인 회원이 아닌 공장과 생성자 만 공유 할 수있는 방법이 있는지 알고 싶습니다.

+0

거의 작동합니다. 예상되고 관찰 된 행동은 무엇입니까? –

+4

문장 끝 부분에 물음표를 넣는 것만으로도 유용한 질문이되지는 않습니까? –

+0

팩트 클래스에만 액세스를 제한하는 것이 올바른 방법인지는 확실하지 않았습니다. Car 클래스의 모든 private 멤버를 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의 생성자 만 사용할 수있는 방법이 있는지 알고 싶었습니다. 이렇게하면 Car의 모든 private 멤버가 CarFactory :: makeCar()에서 사용할 수있게됩니다. – tylerjw

+0

@tylerjw 편집 된 답변보기 –

+1

@tylerjw 위와 같이 할 것이지만, 추상화의 다른 레이어를 삽입하십시오. 'Car'는'CarFirewall'의 친구입니다.'CarFirewall'은'Car' 생성자를 호출하는 하나의 메소드만을 포함합니다. 'CarFirewall'은'CarFactory'의 친구입니다 ... OK. 신경 쓰지 마. François Andrieux는 단지 이것을 거의했습니다. – 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

이것은 직관적이지 않습니다. 이것은 모든 구현을 숨기고 사용자가 인터페이스 만 볼 수있게하는 좋은 방법입니다. 일반적으로 좋은 연습으로 간주됩니다. 친구 관계 (여러면에서 문제가있는)를 사용하지 않는 것이 유리합니다. –

관련 문제