2017-01-04 4 views
-1

동일한 클래스를 기반으로 객체로 채워진 벡터를 전달하고 싶습니다. std::reference_wrapper과 참조 없음을 모두 수정하지 않았습니다. 이 문제를 해결하는 올바른 방법은 무엇입니까?std :: vector를 매개 변수로 전달하는 올바른 방법은 무엇입니까?

class MyClass 
{ 
public: 
    MyClass(int){}; 
    virtual void print() const { 
     std::cout<<"MyClass"<<std::endl; 
    } 
}; 
class MySubClass : public MyClass 
{ 
public: 
    MySubClass(int a):MyClass(a){}; 
    virtual void print() const { 
     std::cout<<"MySubClass"<<std::endl; 
    } 
}; 
void test(const std::vector<std::reference_wrapper<MyClass>>& v) 
{ 
    for (const auto& c : v) { 
     c.get().print(); 
    } 
} 
void test(const std::vector<MyClass>& v) 
{ 
    for (const auto& c : v) { 
     c.print(); 
    } 
} 
int main() 
{ 
    { 
     MySubClass s(2); 
     std::vector<MyClass> v; 
     v.push_back(s); 
     test(v);//print MyClass, but I need MySubClass 
    } 
    { 
     MySubClass s(2); 
     std::vector<std::reference_wrapper<MyClass>> v; 
     v.push_back(s); 
     test(v);//print MySubClass 
     test({2}); 
     test({s});//wrong ambigious 
    } 
    return 0; 
} 
+2

'const std :: vector & v' - 벡터에 대한 참조를 전달하기 때문에 여기에 'MyClass'의 복사본이 없습니다. – Holt

+6

사과를 오토바이와 비교하고 있습니다 - 참조 벡터 나 물체 벡터를 원하십니까? 그들은 완전히 다른 용도를 가지고 있습니다. 너 뭐하려고? –

+0

@Holt 죄송합니다, 충분히 명확하게하지 않았습니다. 이제 나는 다시 편집했다. –

답변

1
{ 
    MySubClass s(2); 
    std::vector<MyClass> v; 
    v.push_back(s); 
    test(v);//print MyClass, but I need MySubClass 
} 

여기서 문제는 MyClass의 벡터에 MySubClass 개체를 저장하려고 시도하고 있다는 점이다. MySubClass 전체를 저장할 수는 없으며 대신 MyClass 상위 하위 개체 만 저장됩니다. 이는 저장된 객체를 마치 MySubClass 인 것처럼 취급하려는 욕구와 상충됩니다.

{ 
    MySubClass s(2); 
    std::vector<std::reference_wrapper<MyClass>> v; 
    v.push_back(s); 

이렇게하면 이전 문제가 해결됩니다. 참조는 정적 유형의 서브 클래스를 참조 할 수 있습니다. 그러나 객체는 벡터에 저장되지 않습니다. 객체는 지역 변수 s으로 저장되며 벡터에서만 참조됩니다.

test(v);//print MySubClass 
    test({2}); 
    test({s});//wrong ambigious 

여기서 문제

당신이 MySubClass지지 않습니다 어느 것도이 오버로드를 가지고 있지만, 모두 MySubClass의 초기화 목록에서 초기화 할 수있는 일을 받아 들일 것입니다. 따라서 과부하 해결은 어렵습니다. 컴파일러는 호출하려는 과부하를 알지 못합니다.

일반 초기화 목록 대신 명시 적 임시 초기화를 사용하십시오.

test(std::vector<MyClass>{2}); 
    test(std::vector<std::reference_wrapper<MyClass>>{s}); 

오버로드를 사용하지 말고 대신 고유하게 명명 된 기능을 사용하십시오.

void test(const std::vector<std::reference_wrapper<MyClass>>& v) 
void test2(const std::vector<MyClass>& v) 
+0

OP는'std :: vector '를 고려할 수도 있습니다. 그것은 reference_wrapper 버전과 매우 비슷한 동작을하지만 코드 독자에게는 개념적으로 더 간단 할 수 있습니다. –

+0

@MartinBonner 그러나이 편리한 문법은 포인터가'test ({2}) '를 잃을 수도 있습니다. –

+0

@Ringo_D : 맞아. 해당 구문이 유용하다면 포인터는 덜 매력적입니다. (많은 응용 프로그램에서는 그렇지 않습니다.) –