2017-03-01 6 views
2

C++에서 객체 공장 사전 :내가 문자열 주어진 새로운 객체를 검색 할 날 수있는 정적지도 구현해야

헤더 :

static const map<string, function<void(MyObject)>> Dictionary; 

출처 :

const map<string, function<void(MyObject)>> * const ObjectDictionary = boost::assign::map_list_of 
("Car", new MyCarObject()) 
("Ship", new MyShipObject()); 

그러나 컴파일 할 때 문제가 있습니다.

'<function-style-cast>': cannot convert from 'initializer list' to 'std::pair<const char *,MyCarObject *>' 

아니요.이 공장의 사용법은 확실합니다.

어떻게 C++에서이 동작을 구현할 수 있습니까?


참고 : 문자열 주어진

public static class MyFactory 
    { 

     public static readonly Dictionary<string, Func<MyObject>> ObjectDictionary = new Dictionary<string, Func<MyObject>>() 
     { 
      ["Car"] =() => new MyCarObject(), 
      ["Ship"] =() => new MyShipObject(), 
     }; 

    } 

그래서 텍스트 파일을 읽을 수와 개체를 만들 수 있습니다 난 할 노력하고있어 포트에 C++로 C에서 # 내가 과거에했던 몇 가지 코드 :

var getObject = default(Func<MyObject>); 

CurrentObjectDictionary.TryGetvalue(objectName, out getObject); 

if(getObject != null) 
{ 
    MyObject = getObject(); 
    //MyObject.Data = ... 
    //store 
} 
+0

const map > 두 번째 매개 변수는 객체가 아닌 함수입니다. 반면 "Car", new MyCarObject())에는 문자열과 MyCarObject가 포함되어 있습니다. –

+0

나는 그것을 본다 ... 명백한 실수이다. 불행히도 아직 객체를 만드는 함수를 표현하기에는 아직 지식이 부족합니다. 저를 올바른 방향으로 안내해 주시겠습니까? – Sturm

+0

당신이해야 할 일은 typedef std :: function function_t를 만드는 것입니다. 팩토리 함수 function_t func = myfactoryfunc를 작성하십시오. 을 맵에 추가하십시오. –

답변

2

부스트 왕복없이 작성자 기능을 사용하여지도를 직접 초기화 할 수 있습니다.

const std::map<std::string, std::function<unique_ptr<Object>()>> dict{ 
    {"car", [](){ return std::make_unique<MyCarObject>();}}, 
    {"ship", [](){ return std::make_unique<MyShipObject>();}} 
    }; 

http://cpp.sh/5uzjq

사용법 :

auto vehicle = dict.at(vehicle_type)(); 

참고 :

const map<...> dict{ 
    {"car", &std::make_unique<Car>}, 
    {"ship", &std::make_unique<Ship>} 
}; 
+0

은 C++ 11 이후 버전 일 수 있습니다. –

+0

그가 std :: function을 사용하고 있다면 C++ 11. 그들이 진짜 이유가없는 한, C++ 03을 사용하는 누군가를 찾을 수있어서 놀랄 것입니다. –

+0

'yup'과 'nope'문자열을 갖는'Object' 옆의 중괄호의 의미와 요점을 설명해주십시오. 링크 된 코드를 본 후에 생성자처럼 보입니다. – Sturm

1
: 당신은 단지 null의 생성자를 처리하는 경우, 당신도지도에 바로 &std::make_unique<T>를 삽입 할 수 있습니다
class Transport 
{ 
public: 
    virtual ~Transport(); 
    virtual void foo() = 0; 
}; 

class Car : public Transport 
{ 
public: 
    virtual ~Car(); 
    virtual void foo(){ }; 
}; 

class Boat : public Transport 
{ 
public: 
    virtual ~Boat(); 
    virtual void foo(){ }; 
}; 

typedef boost::function<Transport*()> factoryfunc; 

template<typename T> 
static std::unique_ptr<T> CreateObject() 
{ 
    return std::unique_ptr<T>{new T()}; 
} 

class foo 
{ 
public: 
    foo() 
    { 
     map_.insert(std::make_pair("car", CreateObject<Car>)); 
     map_.insert(std::make_pair("boat", CreateObject<Boat>)); 
    } 
    std::map<std::string, factoryfunc> map_; 
}; 
이건 그냥 예입니다

foo obj; 
Transport* carobj = obj.map_["car"](); 

당신에게 아이디어를주고 : 0

이 같이 사용할 수 있습니다. 거기에 당신이 수정하고자 할 수도 삭제 등없이 동적 할당이 있습니다. 중요한 점은 삽입시지도에 무엇이 추가되는지입니다. 그것의 실제 개체가 아니라 서명의 기능을 언급했다. 그런 다음 함수를 호출하여 다음과 같은 객체를 얻습니다. Transport* carobj = obj.map_["car"]();

+0

나는 그 생각에 동의한다. ''템플릿을 클래스 스코프에서 메소드 스코프 :'T * Factory :: Create '로 옮길 수 있습니다. 다음으로'Factory * '를 모두 없애고'T * Create '이라는 무료 함수를 만들 수 있습니다. 다음으로, 소유권을 표현하고 원시 포인터 대신에 'unique_ptr '을 반환하고자 할 것입니다. ... 그리고'std :: make_unique '로 끝납니다. – xtofl

+0

움직이는 범위와 스마트 ptrs에 동의했습니다. 나는 똑똑한 포인터를 사용할 것이다. 그렇기 때문에 나는 그것을 공유하거나 독특한 것으로 요구한다. –

+1

'Create' 함수는 고유 한 소유권을가집니다. 그 소유권을 호출자에게 전송합니다. 발신자는 자신이 적합하다고 생각하는 것을 할 수 있습니다. 소유권을 이전하거나 공유 할 수 있습니다. 'unique'을'shared'로 변환하는 것은 무료입니다. 공유 된 소유권은 매우 드문 것으로,이 https://herbsutter.com/2013/05/30/gotw-91-smart-pointer-parameters/에서 매우 흥미로운 기사입니다. – xtofl