2010-08-19 6 views
1

기본적으로 ID를 검색하여 해당 포인터 유형으로 캐스팅하는 ID 번호로 인덱싱 된 객체 (셰이프)의 hash_map을 둘러싼 래퍼 인 데이터베이스 클래스에 대한 함수를 작성하려고합니다.함수에서 형식을 인수로 사용할 수 있습니까?

나는 이런 식으로 할 수 있기를 바란다 :

Circle* shapeToLookup = NULL; 
int idNum = 12; 
database.lookup(idNum, circleToLookup); 
if(circleToLookup != NULL) 
{ 
    // Do stuff with the circle. 
} 

그리고 데이터베이스에 인수의 형식을 알리라고 권한다. 함수 오버로드 (lookup(int, Circle*), lookup(int, Rect*), 광고 nauseum)없이이 작업을 수행 할 수있는 방법이 있습니까? lookup(int, Shape*)과 같은 함수를 선언하고 어떤 유형을 부여했는지 알 수 있습니까?

감사합니다.

+0

, 이것은 정말로 데이터베이스 질문입니다. 당신은 또한 어떤 DB를 말하지 않습니다. SQL 키워드 "LIKE"를 살펴 보겠습니다. – JustBoo

+0

유형 정보를 데이터베이스에 전달하는 방법은 무엇입니까? (또는 내가 말해야 할 것은, 데이터베이스가 그것을 어떻게 받아 들여야 하는가?) –

+0

데이터베이스가이 정보를 가지고 * 수행하기를 원한다면, 당신은 원 - 특정 코드, 몇몇 직사각형 특정 코드 등을 써야 할 것이다. 광고 구역. 질문은 *이 코드를 어디에 넣고 싶은지입니다. 데이터베이스에서 수행 할 작업을 지정할 수 있습니까? – Beta

답변

3

템플릿으로 할 수 있습니다.

편집 : 추가 정보를 기반으로 한 새로운 구현입니다.

template <typename T> 
void lookup(int idNum, T* &ptr) { 
    auto it = mymap.find(idNum); 
    if (it == mymap.end()) { 
     ptr = 0; 
    } else { 
     ptr = dynamic_cast<T*>(*it); // Shape must have a virtual member function 
    } 
} 

또는 당신이 선호 수 있습니다 : mymapstd::map<int, Shape*> 경우 그런

template <typename T> 
T* lookup(int idNum) { 
    auto it = mymap.find(idNum); 
    if (it == mymap.end()) { 
     return 0; 
    } 
    return dynamic_cast<T*>(*it); 
} 

자체가 재미의 전체 힙이 Circle *circle = database.lookup<Circle>(123);

분명히 다형성 용기처럼 부르지 만, 나는거야 그걸 정렬했다고 가정하십시오. 내가 빠뜨린 어딘가에 shared_ptr이있을 수 있습니다.

올드 구현 나는 DB는 POD의 사본을 저장할 수 있습니다 생각했을 때 :

template <typename T> 
void lookup(int idNum, T* &ptr) { 
    void *theresult = // something based on idNum 

    // some check needed here that theresult really is the right type. 
    // how you do this depends on the database, but suppose that 
    // the database gives us some integer "type" which indicates the type 
    if (type != type_constant<T>::value) { 
     ptr = 0; 
    } else { 
     ptr = static_cast<T*>(theresult); 
    } 
} 

type_constant는 "유형의 특성"의 예입니다, 당신이 좋아 구현 :

template <typename T> 
struct type_constant {}; 

template <> 
struct type_constant<Circle> { 
    static const int value = 1; 
}; 

template <> 
struct type_constant<Rectangle> { 
    static const int value = 2; 
}; 

// etc... 
IMO
+0

우리는 아이들 타입으로 캐스트하기 위해 dynamic_cast <>를 사용하지 않아야합니다. (즉 Shape *에서 Circle *로)? –

+0

아마도. 나는이 데이터베이스가 실제로 리턴하는지 모른다. 참조가 서브 클래스 인'Shape * '이고'Shape *'에 가상 멤버 함수가 있다면 yes이다. 데이터베이스 자체가 객체 기반이 아니면, 어딘가에서 유형을 나타내는 레코드를 기반으로 무언가를해야합니다. 'Shape * '이 실제 기본 클래스인지 질문자가 솔루션의 일부라고 생각한다고 언급 한 것인지는 질문 할 수 없습니다. –

+0

'type_constant'에 ​​대해 몰랐고 마틴이 언급 ​​한 것처럼'dynamic_cast'를 살펴볼 것입니다. 템플릿을 바로 생각하지 않기위한 얼굴 표정. – spbots

0

다른 사람들은 함수 템플릿을 사용하여 함수에 형식을 전달하는 방법을 설명했습니다. 나는 다른 관점을주고 싶습니다

Shape에 새로운 가상 함수를 소개하고 Cricle 클래스의 가상 함수의 재 구현에 Do stuff with the Circle 부분을 이동하는 더 나은 수 있습니다.

그런 식으로 유형을 알아야 할 필요가 없습니다. 데이터베이스에서 Shape 개체를 가져온 다음 doStuff() 함수를 호출하면 실제 유형 인 Shape에 따라 올바른 작업을 수행 할 수 있습니다. 가상 함수를위한 좋은 유스 케이스. :-)

실제로 이것은 Do stuff의 실제 상황에 따라 다소 복잡 할 수 있습니다.

+0

불행하게도 이것은 "셰이프"가 모두 서로 의존적 인 레거시 코드에서 중요한 리팩토링 작업입니다. 따라서 조회가 실제로 다른 셰이프 내부에서 발생하고 doStuff()가 반드시 공통 기능이 될 필요는 없습니다. 고마워요 :) – spbots

4
template <T> 
Database::lookup(int idNum, T TobjectToLookup) 
{ 
    // inside here, T is the type of the object passed in/ 
} 
관련 문제