가상 멤버 함수 (virtual function)
동적 바인딩을 위해 사용
class A
{
public:
virtual void sub(void);
};
[예제] 함수 재정의(overriding) 주의사항
#include <iostream>
class Animal
{
public:
void Cry() { std::cout << "Cry..." << std::endl; }
};
class Dog : public Animal
{
public:
void Cry() { std::cout << "멍멍" << std::endl; }
};
int main()
{
Animal a;
a.Cry(); // Animal cry
Dog d;
d.Cry(); // Dog cry
Animal* p = &d; // upcasting
p->Cry(); // ??? -> Dog? Animal?
}
Q) p->Cry(); 에서 Aniaml 객체, Dog 객체 중 어떤 Cry() 호출할까?
A) Animal cry()
실제 객체는 Dog 이지만 upcasting 되어 Animal* p 만들어져 있다.
java, python 등에서는 Dog cry가 호출되지만
C++에서는 기본적으로 Animal cry가 호출된다. (static binding)
[예제] 가상함수 적용
#include <iostream>
class Animal
{
public:
virtual void Cry() { std::cout << "Cry..." << std::endl; } // 1
};
class Dog : public Animal
{
public:
virtual void Cry() { std::cout << "멍멍" << std::endl; } // 2
};
int main()
{
Dog d;
Animal* p = &d;
p->Cry(); // 2
}
📍 주요 특징
• 클래스의 멤버함수만 가상함수로 둘 수 있으며
전역함수는 가상 함수로 둘 수 없다.
• runtime에 함수 바인딩을 진행해야 하므로
가상함수 남용은 프로그램 수행 속도를 떨어뜨릴 수 있다.
• 파생 클래스에서 virtual 예약어가 필수는 아니지만 가독성을 위해서 권장
Q) 기반클래스 설계 시 어떤 멤버함수를 가상함수로 둘까?
A) 파생 클래스 "공통"은 기반 클래스에도 있어야 한다.
파생클래스에서 재정의하게 하는 것이라면 가상함수 적용
[예제]
파생 클래스의 공통 함수를 Draw() 기반 클래스에 구현
#include <iostream>
#include <vector>
using namespace std;
class Shape
{
public:
void Draw() { cout << "Shape..." << endl; } // 파생 클래스의 공통 함수
};
class Rect : public Shape
{
public:
void Draw() { cout << "Rect..." << endl; }
};
class Circle : public Shape
{
public:
void Draw() { cout << "Circle..." << endl; }
};
class Triangle : public Shape
{
public:
void Draw() { cout << "Triangle..." << endl; }
};
int main()
{
vector<Shape*> v;
while (1)
{
int cmd;
cin >> cmd;
if (cmd == 1) v.push_back(new Rect);
else if (cmd == 2) v.push_back(new Circle);
else if (cmd == 3) v.push_back(new Triangle);
else if (cmd == 9)
{
for (auto p : v)
{
p->Draw(); // Shape...
}
}
}
}
[예제]
파생클래스에서 재정의하게 하는 것이라면 가상함수 적용
#include <iostream>
#include <vector>
using namespace std;
class Shape
{
public:
virtual void Draw() { cout << "Shape..." << endl; }
};
class Rect : public Shape
{
public:
virtual void Draw() { cout << "Rect..." << endl; }
};
class Circle : public Shape
{
public:
virtual void Draw() { cout << "Circle..." << endl; }
};
class Triangle : public Shape
{
public:
virtual void Draw() { cout << "Triangle..." << endl; }
};
int main()
{
vector<Shape*> v;
while (1)
{
int cmd;
cin >> cmd;
if (cmd == 1) v.push_back(new Rect);
else if (cmd == 2) v.push_back(new Circle);
else if (cmd == 3) v.push_back(new Triangle);
else if (cmd == 9)
{
for (auto p : v)
{
p->Draw(); // 실제 객체의 Draw (동적 바인딩)
}
}
}
}
[C++] Upcasting
Upcasting• 기반 클래스 포인터로 파생 클래스 객체를 가리킬 수 있다.• 기반 클래스 포인터로는 기반 클래스 멤버만 접근 가능• 파생 클래스 접근하려면 static_cast 필요 [예제] upcasting 이란class
zoosso.tistory.com
[C++] 함수 바인딩 (Funciton Binding)
함수 바인딩 (Funciton Binding)표현식을 어느 함수와 연결할지 결정하는 과정 [예제] function binding#include class Animal{public: // static binding void Cry1() { std::cout Cry1(); // ??? -> 1 p->Cry2(); // ??? -> 4} ✔️ static
zoosso.tistory.com
댓글