#include
<iostream>
using namespace std;
class Parent
{
int x;
public:
virtual void foo() { cout <<" Parent::foo" << endl;}
};
class Child : public Parent
{
int y;
public:
virtual void foo() { cout << "child::foo"<< endl; }
// 가상함수는inline 될수없다. inline : 컴파일시수행. 가상함수: 실행시간수행
};
int main()
{
Parent p;
cout << sizeof(p) << endl; // p 는4바이트가아니고8바이트(가상함수테이블포인터추가)
Child c;
cout<< sizeof(c) << endl; // x,y까지8바이트+ 가상함수테이블포인터4바이트= 12바이트
Parent* pc = &c;
pc->foo();
// (*pc)[0]()의기계어코드를만들어낸다.이게 포인트다. 이름을 보지 않고 배열의 인덱스로 함수를
// 찾아간다. 이걸 기억해두고 아래 문제를 생각한다. 결국 이 코드는
// 가상함수테이블의첫번째공간으로..어디로 갈지 실행시간에(vptr을 보고) 결정된다
}
class A
{
int x;
public:
virtual void foo() { cout << "A::foo" << endl; }
};
class B // A와상속관계가아님
{
int y;
public:
virtual void goo() { cout << "B::goo" << endl; }
};
int main()
{
A a;
B* p = (B*)&a;
p->goo(); // 둘다가상함수가아니라면B:goo() 가실행된다.
}
// foo와goo 가둘다가상함수라면foo()가호출.
// (코드에서타입은B* 이지만&a가대입되어a의주소를가진다.따라서가상함수테이블도A의그것으로가진다.
// 런타임시간에p->goo 는B의goo 가있는줄알고가상함수테이블을따라가서(첫번째로간다) 그곳을참조하는데가보니까
// A::foo 가있어서호출해버린다-_-.. 배열인덱스처럼따라간다.)
// foo 가 가상이고 goo가 가상이 아니라면 goo()가호출. A는 vptr이 있지만 B는 vptr이 없다. 그래서 A를 대입해도 B는 테이블을 안만든다. 그래서 그냥 goo로..
// goo 가 가상이 아니고 goo가 가상이라면 에러.(쓰레기값을참조한다) A 함수에는 vptr이 없다고!
class A
{
public:
virtual void foo() { cout << "A::foo" << endl; }
};
class B : public A
{
public :
virtual void foo() { cout << " B:: foo " << endl; }
};
void hoo(A* p, A& r, A o)
{
p->foo(); // B::foo
r.foo(); // B::foo
o.foo(); // 값으로전달받는다. A::foo
}
int main()
{
B b;
hoo(&b,b,b);
}
클래스에 가상 함수가 포함되면 클래스 멤버에 vptr이라는 포인터가 추가된다. 코드에는 나타나지 않고 디버그중에 조사식으로 확
인할 수 있다. vptr은 해당 클래스의 가상함수 테이블의 주소를 가지고 있다. 해당 클래스의 virtual 선언에 따라 클래스가 실행해야
할 가상함수의 함수포인터가 배열을 이루고 있음을 확인할 수 있다. 이것을 가상 함수 테이블이라 한다.
'Programing > C++' 카테고리의 다른 글
이중연결리스트.h (0) | 2016.11.30 |
---|---|
스마트 포인터 (0) | 2016.11.30 |
템플릿(Template) -클래스 템플릿, 템플릿의 특수화 (0) | 2016.11.30 |
템플릿(Template) - 함수 템플릿, 클래스 템플릿, 템플릿의 특수화 (0) | 2016.11.30 |
클래스 (0) | 2016.11.30 |