2012-10-24 4 views
9

기본 클래스가 있고 가상 메서드 만 있고 의 2 개의 파생 클래스가 있고 이러한 가상 메서드가 구현되어 있습니다.기본 클래스의 배열에 대한 포인터, 파생 클래스로 채우기

은 어떻게 I :

// causes C2259 
BaseClass* base = new BaseClass[2]; 

BaseClass[0] = new FirstDerivedClass; 
BaseClass[1] = new SecondDerivedClass; 

나 :

// causes "base is being used without being initialized" 
BaseClass* base; 
// causes CC59 again 
BaseClass* base = new BaseClass; 

base[0] = FirstDerivedClass(); 
base[1] = SecondDerivedClass(); 

(또는 비슷한)

... 나는 DerivedClass 통해 BaseClass의 방법에 액세스 할 수 있도록 그러나 포인터에 의해 포인터는 DerivedClass s의 배열입니까?

답변

8

배열이 잘못된 형식의이다 : 그것은 BaseClass 객체를 저장 포인터 대신 대신 인스턴스가 있습니다. BaseClass이 추상적 인 것처럼 보이기 때문에 컴파일러는 배열을 채우기 위해 인스턴스를 기본 생성 할 수 없다는 불평을합니다.

추상화가 아니더라도 배열을 다형성으로 사용하면 C++에서 big no-no이되므로 어떤 경우에도 다르게해야합니다. 에 코드를 변경하여

수정이 : 말했다

BaseClass** base = new BaseClass*[2]; 

BaseClass[0] = new FirstDerivedClass; 
BaseClass[1] = new SecondDerivedClass; 

는 대부분의 시간을 대신 벙어리 포인터 대신 일반 배열 (예 : std::shared_ptr 등) 스마트 포인터의 std::vector을 사용하는 것이 바람직하다. 수동으로 코드를 작성하는 대신 이러한 도구를 사용하면 매우 짧은 런타임 비용으로 많은 문제를 투명하게 처리 할 수 ​​있습니다. 당신의 BaseClass로 순수 가상 메서드가 포함되어있는 경우

+1

"object slicing"이라고 불리는이 문제는 배열과 관련이 없습니다. 파생 클래스를 값 *에 의해 기본 클래스 *에 할당 할 때마다 발생합니다. 예 : 'BaseClass b; b = FirstDerivedClass();'는 compileable C++입니다. 그럼에도 불구하고 자동으로 중단됩니다 (기껏해야 컴파일러 경고를받을 수 있습니다). –

+0

링크가 이동 된 것 같습니다. – user6003859

+1

@ user6003859 업데이트했습니다. 감사합니다. – Jon

3

이 C 대신 간단한 배열의 std::vector를 사용 ++입니다 : 가장 안전한 방법은 사용하는 것입니다 발견

std::vector<BaseClass*> base; 
base.push_back(new FirstDerivedClass()); 
base.push_back(new SecondDerivedClass()); 

Kerrek SB으로 std::unique_ptr :

std::vector<std::unique_ptr<BaseClass> > base; 
base.push_back(std_unique_ptr<BaseClass>(new FirstDerivedClass())); 
base.push_back(std_unique_ptr<BaseClass>(new SecondDerivedClass())); 
+2

하지만 배열을 원한다면? – Deukalion

+1

무엇을 원하십니까? 속도? 신뢰할 수 있음? –

+0

어떨까요 : BaseClass * Base [2]; Base [0] = new FirstDerivedClass; 기본 [1] = 새 SecondDerivedClass; – Al2O3

2

,이 컴파일 실패합니다

BaseClass* base = new BaseClass[2]; 

그것을, 당신은 메모리 누수를 얻을려고하지 않습니다.

C++에서는 std :: vector 또는 std :: array를 사용하여 스마트 포인터를 사용합니다. 예를 들어

std::vector< std::shared_ptr<BaseClass> > arr(2); 
arr[0].reset(new FirstDerivedClass()); 
arr[1].reset(new SecondDerivedClass()); 
+0

OP의 코드에서 더 중요한 문제는 프로그램을 자동으로 중단시키는 * object slicing *입니다. –

+0

@j_random_hacker 그래서 나는 어떤 종류의 스마트 포인터를 사용할 것을 제안했다. 기본 유형의 객체를 저장하면 (순수 함수가없는 경우) 슬라이스가 발생합니다. –

0

BaseClass* Base[2]; 

Base[0] = new FirstDerivedClass; 
Base[1] = new SecondDerivedClass; 
+1

원본 코드가 수행하려고했던 작업과 매우 다른 작업을 수행합니다. 이 배열은 원래 힙에있는 동안 스택에 할당됩니다. – Jon

+0

네, 그렇 겠지요. 이제 배열은 포인터이고 배열에 포인터가 있습니다. – Deukalion

0

(Rubby)에서의 응답이 '포인터 배열을 정의하고, 포인터 타입 BaseClass로이다. 파생 클래스에 대한 포인터를 배열 요소에 지정하십시오. 처럼 :

BaseClass* base [2]; 
base[0] = new FirstDerivedClass; 
base[1] = new SecondDerivedClass; 
관련 문제