[전재] 허함수와 구조함수, 분석함수
구조 함수는 허함수일 수 없다
4
4
4
4
분석 함수는 허함수일 수도 있고, 심지어는 순허함수일 수도 있다
대상을 대상으로 프로그래밍하는 과정에서 기류의 바늘이나 인용은 보통 기류나 파생류의 대상을 가리킨다. 만약에 기류의 분석 함수가 허함수가 아니라면 바늘이나 인용을 삭제하여 대상을 방출할 때 기류의 분석 함수만 호출하고 파생류의 분석 함수는 호출하지 않아 메모리가 유출된다.반대로 만약에 기류의 분석 함수가 허함수라면 이런 문제가 발생하지 않을 것이다.따라서 하나의 클래스가 다른 클래스의 기본 클래스로 사용되려고 할 때, 그 분석 함수는 반드시 허함수여야 한다.다음과 같은 예를 고려하십시오.
class A
{
public:
A() { ptra_ = new char[10];}
~A() { delete[] ptra_;} //
private:
char * ptra_;
};
class B: public A
{
public:
B() { ptrb_ = new char[20];}
~B() { delete[] ptrb_;}
private:
char * ptrb_;
};
void foo()
{
A * a = new B();
delete a;
}
이 예에서 delete a를 실행할 때 실제로는 A:~A()만 호출되었고 B류의 분석 함수는 호출되지 않았다.위의 A::~A()를virtual로 바꾸면 B::~B()도 deletea에서 호출되었음을 보증할 수 있습니다.따라서 기류의 분석 함수는 모두virtual이어야 한다.그러나 일반적으로 기본 클래스의 클래스 분석 함수를 하지 않으면 허함수라고 성명하지 않는다. 허함수의 실현은 대상이 추가 정보를 가지고 시스템 비용을 추가해야 하기 때문에 대상의 메모리 공간에 vptr를 추가해야 한다. 이 바늘은 vtable을 가리킨다.분석 함수는 순허함수일 수 있다. 보통 하나의 클래스를 추상류로 설정하고 이 클래스가 적당한 함수가 순허화될 수 없을 때 순허의 분석 함수를 사용하여 목적을 달성할 수 있다.그러나 순수 허의 분석 함수는 다른 순수 허 함수와 다르다는 점은 순수 허의 분석 함수는 그 정의를 제공해야 하고 다른 순수 허 함수는 성명만 제공하면 된다는 것이다. 왜냐하면 파생 클래스의 대상을 방출할 때 그 분석 함수는 최종적으로 추상 클래스와 같은 층으로 호출되고 추상 클래스의 허구 함수를 호출하며 추상 클래스의 분석 함수가 정의되지 않으면 컴파일할 때 오류가 발생할 수 있기 때문이다.
다태와 허함수
허함수는 C++에서 다태적 실현을 위한 메커니즘으로 핵심 이념은 기본 클래스를 통해 파생 클래스 정의에 접근하는 함수이다.
다태적 용도
대상을 대상으로 하는 프로그래밍에서 먼저 데이터에 대해 추상적(기본 클래스 확정)과 계승(파생 클래스 확정)을 하고 클래스 차원을 구성한다.이 클래스의 사용자가 그들을 사용할 때 만약에 클래스가 필요할 때 클래스에 대한 코드를 쓰고 파생 클래스가 필요할 때 파생 클래스에 대한 코드를 쓰면 클래스가 사용자 앞에 완전히 노출되는 것과 같다.만약 이 클래스의 차원에 어떤 변화가 있다면 (새로운 클래스가 추가되었음) 사용자가 알아야 한다. (새로운 클래스에 대한 코드 쓰기)이렇게 하면 클래스 차원과 사용자 간의 결합을 증가시켰다. 어떤 사람들은 이런 상황을 프로그램의'bad smell'중 하나로 열거했다.다태는 프로그래머로 하여금 이런 곤경에서 벗어나게 할 수 있다. 하나의 기본 지침이나 인용을 통해 하나의 허함수를 호출하면 서로 다른 파생류의 함수를 실제적으로 호출하는 효과를 얻을 수 있고 클래스 차원과 사용자 간의 결합을 낮출 수 있다.
동적 연결 방법
컴파일러는 어떻게 허함수에 대해 다시 실행할 때 호출된 함수를 확정할 수 있는 코드를 생성합니까?즉, 허함수는 실제로 어떻게 컴파일러에 의해 처리됩니까?Lippman은 C++ 대상 모델을 깊이 있게 탐색했다[1]에서 서로 다른 장에서 몇 가지 방식을 설명했는데 여기서'표준적인'방식을 간단하게 소개한다.'표준'방식, 즉'vtable'메커니즘.컴파일러는 클래스에virtual로 명시된 함수가 있음을 발견하면, 이를 위해 허함수표, 즉 vtable를 생성합니다.vtable는 실제적으로 함수 바늘의 수조로 모든 허함수가 슬로트를 차지한다.하나의 클래스는 대상이 몇 개든지 상관없이 vtable만 있습니다.파생류는 자신의 vtable가 있지만 파생류의 vtable는 기본 클래스의 vtable와 같은 함수 배열 순서가 있고 같은 이름의 허함수는 두 그룹의 같은 위치에 놓여 있다.클래스 대상을 만들 때, 컴파일러는 모든 실례의 메모리 레이아웃에 vptr 필드를 추가합니다. 이 필드는 클래스의 vtable을 가리킵니다.이러한 수단을 통해 컴파일러는 빈 함수 호출을 볼 때 이 호출을 덮어씁니다.
void bar(A * a){ a->foo(); }
다음으로 덮어쓰기:
void bar(A * a){ (a->vptr[1])(); }
파생 클래스와 기본 클래스의foo () 함수는 같은 vtable 인덱스를 가지고 있고, 그들의 vptr는 다른 vtable를 가리키기 때문에, 이러한 방법을 통해 실행 시간에 어떤foo () 함수를 호출할지 결정할 수 있습니다.실제 상황은 결코 이렇게 간단하지 않지만 기본 원리는 대체로 이렇다.
구조 함수와 분석 함수 중의 허함수 호출
하나의 종류의 허함수가 자신의 구조 함수와 분석 함수에서 호출될 때, 그것들은 보통 함수로 변하여 허함수가 되지 않는다.즉 구조 함수와 분석 함수에서 자신을'다태적'으로 만들 수 없다는 것이다.구조 함수 내부에 허함수가 있을 때 자신의 클래스에 있는 허함수만 호출한다. 호출할 때 파생 클래스 버전의 정보가 없기 때문이다.분석 함수 내부에 허함수가 있을 때 구조 함수와 같이'국부'버전만 호출된다. 파생류 버전의 정보가 신뢰할 수 없기 때문이다.분석 함수의 호출 순서는 구조 함수와 반대로 파생류의 분석 함수에서 기류의 분석 함수까지이다.어떤 클래스의 분석 함수가 호출되었을 때 이 클래스에서 파생된 클래스의 분석 함수는 이미 호출되었고 상응하는 데이터도 잃어버렸다. 만약에 허함수의 마지막 버전을 다시 호출한다면 신뢰할 수 없는 데이터에 대해 조작하는 것과 같아서 이것은 매우 위험하다.따라서 분석 함수에서 허함수 메커니즘도 작용하지 않는다.
허함수 사용 시기
기류를 설계할 때, 만약 함수가 파생류에서 서로 다른 표현을 필요로 하는 것을 발견한다면, 그것은 반드시 허구일 것이다.디자인의 측면에서 볼 때 기류에 나타난 허함수는 인터페이스이고 파생류에 나타난 허함수는 인터페이스의 구체적인 실현이다.이런 방법을 통해 대상의 행위를 추상화할 수 있다.
Things to Remember
4
4
4
4
문제: 만약에 기류에서 어떤 함수를 허함수로 성명한다면 두 파생류 중 하나는 이 함수를 다시 정의하고 다른 하나는 이 함수를 허함수로 성명하면 두 파생류의 허함수표는 무엇이 다릅니까?(답안은'참고문'의'C++ 허함수표 분석'참조)
참고 문장
1. CSDN | haozlee | Leo의 블로그 | C++ 허함수표 분석
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.