검색결과 리스트
가상 함수에 해당되는 글 3건
- 2009.09.26 순수 가상 함수
- 2009.09.25 가상 함수의 활용
- 2009.09.25 가상 함수에 대한 이해
글
순수 가상 함수
Programming/C++ Language
2009. 9. 26. 00:12
순수 가상 함수 는 자바의 Interface와 같은 것이다. 문법은 간단히 =0 만 붙여 주면된다. virtual void Draw()=0; 여기서 함수의 동작을 구현해주고 싶으면 헤더파일에서 virtual voidi Draw()=0{ test(); } 로 구현을 해주면 된다. 이 때, 동작은 Interface를 상속받아 재정의를 한 Draw를 호출할 경우, 항상 먼저, Interface에 구현 되어 있는 test() 를 먼저 호출하고 난 뒤에 재정의된 Draw() 함수 코드가 수행 된다는 것이다.
그리고 순수 가상 함수를 포함하는 클래스는 추상 클래스 이므로 인스턴스를 생성 할 수 없다. 단, 포인터형 변수는 선언 할 수 있다.
그리고 순수 가상 함수를 포함하는 클래스는 추상 클래스 이므로 인스턴스를 생성 할 수 없다. 단, 포인터형 변수는 선언 할 수 있다.
'Programming > C++ Language' 카테고리의 다른 글
namespace (0) | 2010.03.19 |
---|---|
연산자 오버로딩 (0) | 2009.09.30 |
가상 함수의 활용 (0) | 2009.09.25 |
가상 함수에 대한 이해 (0) | 2009.09.25 |
Static Member (0) | 2009.05.31 |
글
가상 함수의 활용
Programming/C++ Language
2009. 9. 25. 23:29
활용 1.
class Rectangle
{
public:
virtual void Show() { ~ };
virtual void Hide() { ~ };
void Move() { Hide(); ~ ; Show(); };
}
class Circle : public Rectangle
{
public:
virtual void Show() { ~ };
virtual void Hide() { ~ };
}
void main()
{
Rectangle R;
Circle C;
R.Move();
C.Move();
}
이 때 결과는 어떻게 될까?
R 은 자신의 move 함수를 C 객체는 부모의 move 함수를 호출 하지만, move 내에 있는 Show와 Hide는 각자 자신의 Show와 Hide 함수를 호출한다. 왜 그럴까?
이유는 간단하다. 묵시적으로 this-> 가 함수앞에 생략 되어 있기 때문이다. this->Show(); this->Move() 같이 말이다. 그래서 R에서 Move를 호출할 때는 Rectangle 클래스에 있는 Show, Hide 함수가 호출 되고, C에서 Move를 호출 할 때는 Circle 클래스에 있는 Show, Hide 함수가 호출 된다.
활용 2.
장기적인 관점에 봤을 때, 재활용성이 높은 클래스를 만들 필요가 있다. 이를 위해서, 파생 클래스에서 재정의 할 수 있도록, 재정의할 함수는 가상 함수로 사용하도록 하자. 가령, Student Management 라는 클래스가 있고, 여기에 Add, Remove, Edit, Dump 라는 함수 가 있을 때, Dump 하는 방법을 다르게 구현 할 필요가 있을 수 있다. 그럴 때는 Student MAnagemnt 클래스를 상속 받아서, Dump를 virtual 로 재 정의 하여, 원하는 방식대로 dump 를 할 수 있다. 즉, 재활용 높은 클래스를 만들고자 할 경우, 앞으로 재정의 할 가능성이 있는 함수를 구현 할 때는 virtual 을 선언하여, 재정의 가능 하도록 구현을 하자.
활용 3.
가상 소멸자를 사용 할 필요가 있다. Parent 클래스, Child 클래스가 있을 경우 Child 는 Parent를 상속하는 클래스라고 하자. 이때, Parent 와 Child 의 생성자에서 자원을 할당 하고, 이를 소멸자에서 자원을 해제한다고 할 때, Parent 포인터를 사용하지 않는다면, 정상적으로 생성자 소멸자가 동작하여, 자원을 정상적으로 생성, 해제 할 수 있다. 하지만 Parent* pParent 를 사용하여 Child를 대입 했을 경우, Delete pParent 를 할 경우, 부모의 소멸자만 동작을 하게되고, Chlid 의 자원을 해제 못하게 되어 누수가 될 것이다. 이 때, 소멸자를 virtual 로 선언을 하게 되면, Child 의 소멸자가 호출되고, Parent의 소멸자가 호출되어 자원이 정상적으로 해제 될 것이다.
class Rectangle
{
public:
virtual void Show() { ~ };
virtual void Hide() { ~ };
void Move() { Hide(); ~ ; Show(); };
}
class Circle : public Rectangle
{
public:
virtual void Show() { ~ };
virtual void Hide() { ~ };
}
void main()
{
Rectangle R;
Circle C;
R.Move();
C.Move();
}
이 때 결과는 어떻게 될까?
R 은 자신의 move 함수를 C 객체는 부모의 move 함수를 호출 하지만, move 내에 있는 Show와 Hide는 각자 자신의 Show와 Hide 함수를 호출한다. 왜 그럴까?
이유는 간단하다. 묵시적으로 this-> 가 함수앞에 생략 되어 있기 때문이다. this->Show(); this->Move() 같이 말이다. 그래서 R에서 Move를 호출할 때는 Rectangle 클래스에 있는 Show, Hide 함수가 호출 되고, C에서 Move를 호출 할 때는 Circle 클래스에 있는 Show, Hide 함수가 호출 된다.
활용 2.
장기적인 관점에 봤을 때, 재활용성이 높은 클래스를 만들 필요가 있다. 이를 위해서, 파생 클래스에서 재정의 할 수 있도록, 재정의할 함수는 가상 함수로 사용하도록 하자. 가령, Student Management 라는 클래스가 있고, 여기에 Add, Remove, Edit, Dump 라는 함수 가 있을 때, Dump 하는 방법을 다르게 구현 할 필요가 있을 수 있다. 그럴 때는 Student MAnagemnt 클래스를 상속 받아서, Dump를 virtual 로 재 정의 하여, 원하는 방식대로 dump 를 할 수 있다. 즉, 재활용 높은 클래스를 만들고자 할 경우, 앞으로 재정의 할 가능성이 있는 함수를 구현 할 때는 virtual 을 선언하여, 재정의 가능 하도록 구현을 하자.
활용 3.
가상 소멸자를 사용 할 필요가 있다. Parent 클래스, Child 클래스가 있을 경우 Child 는 Parent를 상속하는 클래스라고 하자. 이때, Parent 와 Child 의 생성자에서 자원을 할당 하고, 이를 소멸자에서 자원을 해제한다고 할 때, Parent 포인터를 사용하지 않는다면, 정상적으로 생성자 소멸자가 동작하여, 자원을 정상적으로 생성, 해제 할 수 있다. 하지만 Parent* pParent 를 사용하여 Child를 대입 했을 경우, Delete pParent 를 할 경우, 부모의 소멸자만 동작을 하게되고, Chlid 의 자원을 해제 못하게 되어 누수가 될 것이다. 이 때, 소멸자를 virtual 로 선언을 하게 되면, Child 의 소멸자가 호출되고, Parent의 소멸자가 호출되어 자원이 정상적으로 해제 될 것이다.
'Programming > C++ Language' 카테고리의 다른 글
namespace (0) | 2010.03.19 |
---|---|
연산자 오버로딩 (0) | 2009.09.30 |
순수 가상 함수 (0) | 2009.09.26 |
가상 함수에 대한 이해 (0) | 2009.09.25 |
Static Member (0) | 2009.05.31 |
글
가상 함수에 대한 이해
Programming/C++ Language
2009. 9. 25. 23:09
가상 함수 의 기본 개념은 책에 다 나와있을 뿐더러, 다들 많이 알기 때문에 개념에 대해서는 간단히 설명 하도록 하겠다.
가상 함수란 동적 결함을 하는 함수이다. 일반적인 함수는 컴파일 시점에서, 이미 어디로 갈지 정적 결합이 일어나지만, 가상 함수의 경우에는 포인터 타입에 실제로 어떤 값이 들어갈지 컴파일 시점에 알 수 없기 때문이다.
자, 그럼 이러한 동적 결합은 어떻게 구현 되는 것일까? 가상 함수를 어떻게 구현 하라는 명시적인 방법은 없으며, 컴파일러 마다 틀리다. 어쨌든, 가상 함수에 맞도록 동작만 하면 된다. 하지만 일반적으로 vtable( 가상 함수 테이블 ) 이라는 가상 함수 목록을 작성하고, 각 객체에 vtable 을 가라키는 숨겨진 멤버 vptr 을 추가하는 방식을 사용한다. vtable 에는 클래스에 소속된 가상함수들의 실제 번지수가 기억되어 있다. 그럼 아래의 예를 보면서 좀 더 구체적으로 살펴보자.
보면 B 클래스가 D의 부모 클래스이다. main 문에서는 B* 형이 있고, 여기에 실제 B와, D 클래스를 대입하여, 함수를 호출 하고 있다. 함수 호출 시, 실제 객체에 있는 vtable 에 대한 메모리 구조가 아래와 같이 나와있다.
B 객체에 있는 가상 함수에 대한 메모리 주소가 vtable에 저장되어 있고,
D 객체의 vtable 에는 D객체에 있는 f1, f2 가상 함수의 주소와 B 클래스에 상속받은 f3 함수의 주소가 저장 되어 있다. B포인터 형에 D객체를 대입해서 f3를 호출 했을 때, B객체의 f3를 호출 해야 하기 때문이다.
출처 : www.winapi.co.kr
가상 함수란 동적 결함을 하는 함수이다. 일반적인 함수는 컴파일 시점에서, 이미 어디로 갈지 정적 결합이 일어나지만, 가상 함수의 경우에는 포인터 타입에 실제로 어떤 값이 들어갈지 컴파일 시점에 알 수 없기 때문이다.
자, 그럼 이러한 동적 결합은 어떻게 구현 되는 것일까? 가상 함수를 어떻게 구현 하라는 명시적인 방법은 없으며, 컴파일러 마다 틀리다. 어쨌든, 가상 함수에 맞도록 동작만 하면 된다. 하지만 일반적으로 vtable( 가상 함수 테이블 ) 이라는 가상 함수 목록을 작성하고, 각 객체에 vtable 을 가라키는 숨겨진 멤버 vptr 을 추가하는 방식을 사용한다. vtable 에는 클래스에 소속된 가상함수들의 실제 번지수가 기억되어 있다. 그럼 아래의 예를 보면서 좀 더 구체적으로 살펴보자.
보면 B 클래스가 D의 부모 클래스이다. main 문에서는 B* 형이 있고, 여기에 실제 B와, D 클래스를 대입하여, 함수를 호출 하고 있다. 함수 호출 시, 실제 객체에 있는 vtable 에 대한 메모리 구조가 아래와 같이 나와있다.
B 객체에 있는 가상 함수에 대한 메모리 주소가 vtable에 저장되어 있고,
D 객체의 vtable 에는 D객체에 있는 f1, f2 가상 함수의 주소와 B 클래스에 상속받은 f3 함수의 주소가 저장 되어 있다. B포인터 형에 D객체를 대입해서 f3를 호출 했을 때, B객체의 f3를 호출 해야 하기 때문이다.
출처 : www.winapi.co.kr
'Programming > C++ Language' 카테고리의 다른 글
namespace (0) | 2010.03.19 |
---|---|
연산자 오버로딩 (0) | 2009.09.30 |
순수 가상 함수 (0) | 2009.09.26 |
가상 함수의 활용 (0) | 2009.09.25 |
Static Member (0) | 2009.05.31 |