나는 C++에서 어떤 일이 일어날지를 보려고 노력했다. 비슷한 방법으로 객체의 배열을 "끊으려고"Java에서 시도 할 수있다.C++에서 배열을 업 캐스트 한 다음 다른 하위 유형을 넣으려고합니까 (Java ArrayStoreException에서 영감을 얻음)?
Java에서 우리는 Double [] 형식의 배열을 가질 수 있습니다. 예를 들어, Double은 Number의 하위 클래스이므로 Number []로 업 캐스트하고 Array에 Number의 다른 하위 클래스를 추가하려고합니다 (예 : 정수. 코드는 컴파일되지만 런타임에 ArrayStoreException이 발생합니다. Integer 유형은 실제 배열 유형 (런타임시 Double 일 수 있음)과 비교하여 검사되기 때 문에 불일치가 발생하기 때문입니다. 코드는 다음과 같을 수 있습니다.
Double[] ds = new Double[12];
Number[] ns = ds;
ns[0] = 2.3; // OK
ns[1] = new Integer(1); // compiles, but we have ArrayStoreException in runtime
그래서 저는 C++을 어떻게 생각합니까? 같은 트릭을 수행 할 수 있습니까? 런타임에 어떤 일이 발생합니까?
다음은 내가 시도한 코드와 출력입니다.
#include <iostream>
class A
{
public:
A(int v = 0): val(v) {}
virtual void g() {std::cout << val << " in A\n";}
void setVal(int v) {val = v;}
protected:
int val;
};
class B : public A
{
public:
virtual void g() {std::cout << val << " in B\n";}
};
class C : public A
{
public:
C(int v = 0): A(v) {}
virtual void g() {std::cout << val << " in C\n";}
private:
int stuff[10];
};
void f(A* as)
{
as[1] = *(new A(12));
}
void f2(A* as)
{
as[1] = *(new C(22));
}
int main()
{
A* bs = new B[5];
for (int i=0 ; i<5; ++i)
{
bs[i].setVal(i);
bs[i].g();
}
std::cout << std::endl;
f(bs);
for (int i=0 ; i<5; ++i)
{
bs[i].g();
}
std::cout << std::endl;
f2(bs);
for (int i=0 ; i<5; ++i)
{
bs[i].g();
}
}
출력 :
0 in B
1 in B
2 in B
3 in B
4 in B
0 in B
12 in B
2 in B
3 in B
4 in B
0 in B
22 in B
2 in B
3 in B
4 in B
는 C 데이터 만의 경우 모두 예상대로, A 또는 C를 만든 다음 B의 어레이 내부를 복사 않는 복사 데이터 (것을보기 A의 일부가 복사되고 복사 된 요소 다음에 메모리가 손상되지 않습니다.)하지만 B의 메소드가 선택됩니다. 즉, vptr이 복사되지 않았 음을 의미합니다.
그래서 제 질문은 다음과 같습니다
는 그 vptr에서이 기본 할당 연산자에 복사되지 않습니다 같아요. 그렇지? 그것은 우리가 호출 한 B의 메서드를 가지고 있지만 C 객체의 데이터를 가질 수있는 유일한 이유입니까?
일부 런타임 오류가 발생하거나 예기치 않은 일이 발생할 수 있습니까? 내가 의미하는 바는 의 배열이 Bs이지만 A 또는 C의 객체 (은 B가 아니거나 하위 유형이 B이 아닙니다), B에 "외계인"인 객체입니까?
또는 어쩌면 C++ 언어가 명시 적으로 또는 암시 적으로 (예 : ArrayStoreException을 명시 적으로 발생시킬 때 Java와 같은) 이러한 기능을 수행 할 수 없다는 보장이 있습니까?
는 UPD :
A* bs = new B[5];
가 실제로 B 방법 (의 런타임 선택에 중점을 넣어, 마지막 순간에이 줄을 변경
그것을하지 말았어야,이 방법 때문에 분명하다 가상입니다.) 처음에는 B* bs = new B[5];
이고 출력은 동일했습니다.
Java의'Double [] ds'의 C++ 아날로그는'Double * ds []', 즉 포인터의 배열입니다 ** ** 객체의 배열이 아닙니다. –