업 캐스팅은 이전에 설명한 가상 함수, 가상 함수 테이블이랑 연관되어 있습니다. 업 캐스팅은 파생된 클래스 개체를 기본 클래스 개체로 변환하는 프로세스입니다. 파생 클래스가 기본 클래스의 보다 특수화된 버전으로 간주되고 변환이 개체를 상속 계층 구조에서 "위"로 이동하기 때문에 이를 "업 캐스팅"이라고 합니다.
기본 클래스(Animal) | 참고하는 방향 |
파생 클래스(Cat) | ↑ |
업 캐스팅은 일반적으로 객체 지향 프로그래밍의 코드 재사용 및 다형성 기능을 활용하는 데 사용됩니다. 파생 클래스 개체를 기본 클래스 개체로 업 캐스팅하면 기본 클래스 및 파생된 다른 기본 클래스의 멤버와 함수에 액세스할 수 있습니다. 이를 통해 동일한 기본 클래스에서 파생되는 한 다른 유형의 개체에서 작동할 수 있는 코드를 작성할 수 있습니다. 아래 예제는 C++에서 업 캐스팅의 예제입니다.
class Animal {
public:
virtual void makeNoise() {
std::cout << "Some generic animal noise" << std::endl;
}
};
class Cat : public Animal {
public:
void makeNoise() {
std::cout << "Meow" << std::endl;
}
};
int main() {
Cat cat;
Animal* animal = &cat; // Up casting the cat object to an Animal pointer
animal->makeNoise(); // Outputs "Meow"
return 0;
}
이전 포스팅에서도 사용했던 울음소리 예제입니다. 이 예제에서 Cat 클래스는 Animal 클래스에서 파생되며 makeNoise 함수를 재정의하여 고양이가 내는 소음을 출력합니다. cat 개체는 Animal 인터페이스를 통해 액세스할 수 있는 Animal* 포인터로 업캐스트됩니다. Animal 포인터에서 makeNoise 함수를 호출하면 고양이가 내는 소음을 출력합니다. 가리키는 객체가 실제로 Cat 객체이고 Cat 클래스가 이 동작을 제공하기 위해 makeNoise 함수를 재정의했기 때문입니다.
업 캐스팅은 데이터 손실이나 변환 중인 개체에 대한 변경을 포함하지 않으므로 일반적으로 안전합니다. 그러나 파생 클래스 개체가 기본 클래스 개체로 업캐스트되고 파생 클래스에 기본 클래스에 없는 추가 데이터 멤버가 있을 때 발생할 수 있는 개체 슬라이싱의 가능성을 인식하는 것이 중요합니다. 이 경우 기본 클래스 개체에 저장할 공간이 없기 때문에 개체가 업캐스트될 때 추가 데이터 멤버가 손실됩니다.
다운 캐스팅은 업 캐스팅과 반대로 기본 클래스 개체를 파생 클래스 개체로 변환하는 프로세스입니다. 기본 클래스가 파생 클래스의 보다 일반적인 버전으로 간주되고 변환이 개체를 상속 계층 구조에서 "아래로" 이동하기 때문에 "다운 캐스팅"이라고 합니다.
기본 클래스(Animal) | 참고하는 방향 |
파생 클래스(Cat) | ↓ |
다운 캐스팅은 일반적으로 파생 클래스에 특정한 멤버나 함수에 액세스해야 하지만, 기본 클래스에 대한 참조나 포인터가 있는 경우에 사용됩니다. 이렇게 하려면 기본 클래스 개체를 파생 클래스 개체로 다운캐스트해야 파생 클래스의 멤버와 함수에 액세스할 수 있습니다.
다운 캐스팅은 변환되는 개체가 있는지에 대해 가정해야 하기 때문에 위험할 수 있습니다. (캣 클래스를 구현 안했을 수도 있으므로) 이럴 경우, 개체가 실제로 파생 클래스의 인스턴스가 아닌 경우 다운 캐스트가 실패하고 런타임 오류 또는 정의되지 않은 동작이 발생할 수 있습니다. 이러한 문제를 방지하려면 C++의 dynamic_cast 또는 C#의 is 및와 같은 기술을 사용하여 다운 캐스팅하기 전에 객체의 유형을 확인하는 것이 중요합니다. 마찬가지로 아래 예제는 C++에서 다운 캐스팅의 예제입니다.
class Animal {
public:
virtual void makeNoise() {
std::cout << "Some generic animal noise" << std::endl;
}
};
class Cat : public Animal {
public:
void makeNoise() {
std::cout << "Meow" << std::endl;
}
void chaseMouse() {
std::cout << "Chasing a mouse!" << std::endl;
}
};
int main() {
Animal* animal = new Cat(); // Up casting a Cat object to an Animal pointer
Cat* cat = dynamic_cast<Cat*>(animal); // Down casting the Animal pointer to a Cat pointer
if (cat) { // Check if the down cast was successful
cat->chaseMouse(); // Outputs "Chasing a mouse!"
} else {
std::cout << "Error: animal is not a Cat object" << std::endl;
}
return 0;
}
위 예제에서 Cat 클래스는 Animal 클래스에서 파생되며 고양이 전용인 chaseMouse라는 함수가 있습니다. 메인 함수에서 Animal* 포인터가 생성되고 기본 클래스로 업캐스트되는 Cat 개체를 가리킵니다. 그런 다음 Animal* 포인터는 dynamic_cast 연산자를 사용하여 Cat* 포인터로 다운캐스트됩니다.
dynamic_cast 연산자는 가리키는 개체의 유형을 확인하고 개체가 실제로 파생 클래스의 인스턴스가 아닌 경우 null 포인터를 반환합니다. 위 예제에서는 경우 다운 캐스트가 성공하고 고양이 포인터가 Cat 개체를 가리킵니다. 그런 다음 "Chasing a mouse!"라는 메시지를 출력하는 cat 포인터에서 chaseMouse 함수를 호출할 수 있습니다.
Animal 포인터가 가리키는 객체가 만약 고양이 객체가 아닌 경우 다운 캐스트가 실패하고 고양이 포인터가 null로 설정되었을 것입니다. 이 경우 프로그램은 chaseMouse 함수를 호출하는 대신 오류 메시지를 인쇄했을 것입니다.
업 캐스팅과 다운 캐스팅의 차이
업 캐스팅은 파생 클래스 개체를 기본 클래스 개체로 변환하는 프로세스이고, 다운 캐스팅은 기본 클래스 개체를 파생 클래스 개체로 변환하는 프로세스입니다.
업 캐스팅은 데이터 손실이나 변환 중인 개체에 대한 변경을 포함하지 않으므로 일반적으로 안전합니다. 반면에 다운캐스팅은 변환되는 객체의 유형에 대한 가정을 요구하고 객체가 실제로 파생 클래스의 인스턴스가 아닌 경우 런타임 오류 또는 정의되지 않은 동작을 초래할 수 있으므로 위험할 수 있습니다.
업 캐스팅은 일반적으로 객체 지향 프로그래밍의 코드 재사용 및 다형성 기능을 활용하는 데 사용되는 반면 다운 캐스팅은 일반적으로 파생 클래스에 특정한 멤버나 함수에 액세스해야 하지만 참조 또는 기본 클래스에 대한 포인터입니다.
'공부 > 기타' 카테고리의 다른 글
온라인 게임에서 유저들을 관리하기 위해 효율적인 정렬 알고리즘과 그 이유는? (0) | 2022.12.26 |
---|---|
상속할 때 public 상속과 protected 상속의 차이 (0) | 2022.12.26 |
나누기 연산자는 왜 다른 연산자에 비해 느릴까? (0) | 2022.12.22 |
float이 빠를까?, double이 빠를까? (0) | 2022.12.22 |
1차원 배열과 2차원 배열의 성능 및 속도 차이 (0) | 2022.12.21 |