개인 공부 후 정보를 남길 목적으로,
생략되거나 오류가 있을 수 있습니다.
압도적
가상 함수 테이블과 가상을 이해하기 위해 먼저 재정의를 살펴보겠습니다.
코드를 보면 Child는 Parent로부터 물려받고,
func() 함수가 Parent 클래스에 선언되어 있지만, Child 클래스에는 같은 이름의 또 다른 func() 함수가 선언되어 있습니다.
이와 같이 상속받은 함수는 자식 객체에 새롭게 정의된다.
씌우다그것은 말한다.
(이 때 리턴 타입과 함수 파라미터 구성이 일치해야 함)
위의 함수를 실행해보면 각각의 func() 함수가 멋지게 출력되는 것을 확인할 수 있습니다.
문제는 여기서 시작됩니다.
위에서 부모 클래스로 선언한 p 포인터 변수에 자식 객체의 주소를 넣고 func() 함수를 호출하면 하위 클래스의 func()이 아닌 부모 클래스의 func()가 호출된다.
이 현상 정적 바인딩 때문에 나타났다
컴파일러는 컴파일 타임에 변수 p가 Parent 유형임을 확인하고 func() 함수를 변수 p에 바인딩합니다.
이 상태에서 빌드가 종료되고 부모의 func() 함수가 호출됩니다.
대부분의 함수를 호출하는 코드는 컴파일 타임에 고정 메모리 주소로 변환됩니다.
이를 정적 바인딩 또는 초기 바인딩이라고 합니다.
C++에서 가상이 아닌 모든 멤버 함수에는 이러한 정적 바인딩이 있습니다.
-TCP 학교(http://www.tcpschool.com/cpp/cpp_polymorphism_virtual)
즉, 사용할 함수는 컴파일 타임에 정해져 있기 때문에 Parent로 선언된 포인터 변수 p는 Parent 클래스의 func()를 호출한다.
비슷한 상황에서 다음도 존재합니다.
Child 클래스는 Parent 클래스를 상속하지만 Parent 클래스의 func()를 호출하거나 오버로드된 함수 func(int a)를 호출하지 않습니다.
기능이 숨겨져 있기 때문에 숨기기라고 합니다.
이 질문은 객체 지향 프로그래밍의 특징 중 하나인 다형성을 무시하게 만듭니다.
이제 이 문제를 해결하는 방법을 살펴보겠습니다.
가상(가상 기능)
이 문제를 해결하기 위해 C++ ‘가상’함수 선언에 키워드를 추가합니다.
가상 기능문제를 풀다.
C++에서 가상 함수는 파생 클래스에 의해 재정의될 것으로 예상되는 멤버 함수입니다.
이러한 가상 함수는 호출되는 객체의 동적 유형에 따라 다릅니다.
실제로 호출할 함수 결정하다.(런타임에 함수의 다형성을 달성하는 데 사용됩니다.
)-TCP 학교(http://www.tcpschool.com/cpp/cpp_polymorphism_virtual)
함수를 선언할 때 다음 코드와 같이 virtual을 추가하여 함수가 가상임을 컴파일러에 알립니다.
(가상을 사용할 때 함수는 런타임에 함수를 바인딩하는 동적 바인딩을 사용합니다.
)
가상 함수 테이블( vtbl )
VTable(가상 함수 테이블)은 C++에서 가상 함수를 구현하기 위한 내부 메커니즘으로, 가상 함수를 호출할 때 함수 주소를 저장하는 테이블입니다.
각 클래스에 대한 VTable 생성 클래스 객체가 생성될 때마다 해당 클래스의 VTable 포인터가 객체 내부에 저장됩니다.
간단히 말해서 가상 기능 테이블은 다음과 같습니다.
가상 함수 포인터의 배열그것을 사용하여 컴파일러는 재정의 기능을 구별합니다.
컴파일 시 가상 함수를 정의하는 클래스가 있으면 가상 함수 테이블이 생성되어 “rdata” 영역에 기록된다.
“rdata” 영역은 읽기 전용 데이터를 저장하는 메모리 영역입니다.
상수 데이터, 문자열 리터럴 및 프로그램 실행 중에 수정해서는 안 되는 가상 함수 테이블과 같은 데이터를 저장합니다.
일반적으로 코드와 데이터 모두 읽기 전용으로 설정되어 있어 보안 및 안정성 측면에서 유리합니다.
가상 함수 테이블은 클래스 정의가 수정되지 않는 한 프로그램 실행 중에 수정되지 않습니다.
그렇지 않으면 내용이 항상 동일합니다.“rdata” 영역에 저장됩니다.
가상 소멸자
일반 상속의 경우 생성자와 소멸자는 다음과 같은 절차를 통해 호출됩니다.
그러나 부모 클래스를 사용하여 개체를 만들고 소멸자를 호출하면 다음과 같습니다.
하위 클래스의 소멸자가 호출되지 않은 경우 다음과 같은 상황이 발생합니다.
개체에서 사용하는 메모리가 해제되지 않기 때문에 메모리 누수가 발생합니다.
따라서 동적으로 할당된 메모리를 해제해야 하며 이는 소멸자에서 virtual을 사용하여 수행할 수 있습니다.
실제 개체 유형이 하위 클래스인지 확인하고 메모리를 정상적으로 해제합니다.
가상 함수를 사용하여 다형성을 달성하여 코드의 유연성과 확장성을 높일 수 있습니다.
하지만 가상 함수 호출은 일반 함수보다 느리므로 성능에 민감한 곳에서는 가상 함수를 사용하지 않는 것이 좋습니다.