문제

다음 수업을 고려해보세요.

class Base
{
   ...
};

class Derived : public Base
{
   ...
};

이 기능

void BaseFoo( std::vector<Base*>vec )
{
    ...
}

그리고 마지막으로 내 벡터

std::vector<Derived*>derived;

나는 합격하고 싶다 derived 기능하다 BaseFoo, 그러나 컴파일러는 나를 허용하지 않습니다.전체 벡터를 복사하지 않고 어떻게 이 문제를 해결할 수 있나요? std::vector<Base*>?

도움이 되었습니까?

해결책

vector<Base*> 그리고 vector<Derived*> 관련이 없는 유형이므로 이 작업을 수행할 수 없습니다.이에 대해서는 C++ FAQ에 설명되어 있습니다. 여기.

변수를 다음에서 변경해야 합니다. vector<Derived*>vector<Base*> 삽입하고 Derived 그것에 반대합니다.

또한 복사를 방지하기 위해 vector 불필요하게 값이 아닌 const 참조로 전달해야 합니다.

void BaseFoo( const std::vector<Base*>& vec )
{
    ...
}

마지막으로, 메모리 누수를 방지하고 코드를 예외로부터 안전하게 만들려면 힙 할당 개체를 처리하도록 설계된 컨테이너를 사용하는 것이 좋습니다. 예:

#include <boost/ptr_container/ptr_vector.hpp>
boost::ptr_vector<Base> vec;

또는 원시 포인터를 사용하는 대신 스마트 포인터를 유지하도록 벡터를 변경합니다.

#include <memory>
std::vector< std::shared_ptr<Base*> > vec;

또는

#include <boost/shared_ptr.hpp>
std::vector< boost::shared_ptr<Base*> > vec;

각각의 경우에 다음을 수정해야 합니다. BaseFoo 그에 따라 기능합니다.

다른 팁

컨테이너 객체(vector<>), 전달 begin 그리고 end 나머지 STL 알고리즘과 같은 반복자입니다.이를 수신하는 함수는 템플릿화되며 Derived* 또는 Base*를 전달하는지는 중요하지 않습니다.

이 문제는 변경 가능한 컨테이너가 있는 프로그래밍 언어에서 발생합니다.다른 사람이 그 과일 봉지에 레몬을 넣지 않았는지 확신할 수 없기 때문에 변경 가능한 사과 봉지를 과일 봉지로 전달할 수 없습니다. 그 후에는 더 이상 사과 봉지로 간주되지 않습니다.사과 봉지가 변경 가능하지 않다면 과일 봉지로 전달해도 괜찮을 것입니다.공분산/반공분산을 검색합니다.

한 가지 옵션은 템플릿을 사용하는 것입니다.

template<typename T>
void BaseFoo( const std::vector<T*>& vec)
{
 ...
}

단점은 구현이 헤더에 있어야 하고 코드가 약간 부풀어 오른다는 것입니다.각 유형에 대해 서로 다른 함수가 인스턴스화되지만 코드는 동일하게 유지됩니다.사용 사례에 따라 빠르고 더러운 솔루션입니다.

편집합니다. 여기에 템플릿이 필요한 이유는 다른 여러 포스터에서 언급한 것처럼 관련되지 않은 유형에 대해 동일한 코드를 작성하려고 하기 때문입니다.템플릿을 사용하면 이러한 정확한 문제를 해결할 수 있습니다.또한 const 참조를 사용하도록 업데이트했습니다.또한 복사본이 필요하지 않은 경우 벡터와 같은 "무거운" 객체를 const 참조로 전달해야 합니다. 이는 기본적으로 항상 그렇습니다.

일반적으로 기본 포인터의 컨테이너로 시작하지만 다른 방법은 아닙니다.

취득 맷 프라이스의 함수에 어떤 유형을 사용할지 미리 알고 있다면 헤더 파일에서 함수 템플릿을 선언한 다음 해당 유형에 대한 명시적 인스턴스화를 추가할 수 있습니다.

// BaseFoo.h
template<typename T>
void BaseFoo( const std::vector<T*>& vec);

// BaseFoo.cpp
template<typename T>
void BaseFoo( const std::vector<T*>& vec);
{
 ...
}

// Explicit instantiation means no need for definition in the header file.
template void BaseFoo<Base> ( const std::vector<Base*>& vec );
template void BaseFoo<Derived> ( const std::vector<Derived*>& vec );

타사 라이브러리를 다루고 있고 이것이 유일한 희망이라면 다음과 같이 할 수 있습니다.

BaseFoo (*reinterpret_cast<std::vector<Base *> *>(&derived));

그렇지 않으면 다른 제안 중 하나로 코드를 수정하세요.

만약에 std::vector 당신이 요구하는 것을 지원한다면 어떤 캐스트도 사용하지 않고 C++ 유형 시스템을 무력화하는 것이 가능할 것입니다(편집:C++ FAQ Lite에 대한 ChrisN의 링크는 동일한 문제에 대해 설명합니다.

class Base {};
class Derived1 : public Base {};
class Derived2 : public Base {};

void pushStuff(std::vector<Base*>& vec) {
    vec.push_back(new Derived2);
    vec.push_back(new Base);
}

...
std::vector<Derived1*> vec;
pushStuff(vec); // Not legal
// Now vec contains a Derived2 and a Base!

당신 이후로 BaseFoo() 함수는 벡터를 값으로 취하므로 전달한 원래 벡터를 수정할 수 없으므로 제가 작성한 내용은 불가능합니다.하지만 const가 아닌 참조를 사용하고 다음을 사용하는 경우 reinterpret_cast<std::vector<Base*>&>() 당신의 통과 std::vector<Derived*>, 원하는 결과를 얻지 못할 수도 있고 프로그램이 중단될 수도 있습니다.

Java 배열 지원 공변적 하위 유형화, 이를 위해서는 Java가 다음을 수행해야 합니다. 배열에 값을 저장할 때마다 런타임 유형 확인을 수행하십시오..이것도 바람직하지 않습니다.

그들은 관련이 없는 유형이므로 그럴 수 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top