가상 함수는 파생 클래스에서 재정의할 것으로 기대하는멤버 함수를 의미
자신을 호출하는 객체의 동적 타입에 따라 실제 호출할 함수가 결정
#include <iostream>
using namespace std;
class Base {
public:
virtual void func() {
cout << "Base" << endl;
}
// virtual을 붙인 가상함수로 오버라이딩을 가능케함
};
class Derived : public Base {
public:
void func() {
cout << "Derived" << endl;
}
};
void foo(Base& base) {
base.func();
}
int main() {
Base b;
Derived d;
b.func();
d.func();
Base& b0 = d;
b0.func();
Base* b1 = &d;
b1->func();
foo(d);
}
virtual로 함수를 선언했을 때
Base
Derived
Derived
Derived
Derived
virtual로 함수를 선언안했을 때
Base
Derived
Base
Base
Base
#include <iostream>
using namespace std;
class Base {
public:
virtual void func() {
cout << "Base" << endl;
}
// virtual을 붙인 가상함수로 오버라이딩을 가능케함
};
class Derived : public Base {
public:
void func() override {
cout << "Derived" << endl;
}
// 부모가 virtual 선언시 자식 클래스도 암시적으로 virtual 선언
// 함수명 오타 방지 등의 실수를 예방하기 위해 override를 붙임.
};
class Derived1 : public Derived {
public:
void func() {
cout << "Derived1" << endl;
}
};
void foo(Base& base) {
base.func();
}
int main() {
Derived1 d1;
foo(d1);
}
Derived1
virtual 함수로 인해 부모가 아닌 자식클래스의 함수를 호출함
#include <iostream>
using namespace std;
class Character {
private:
int _health;
int _power;
public:
Character(int health, int power) : _health(health), _power(power) {
}
virtual void damaged(int power) {
_health -= power;
}
void attack(Character& target) const {
target.damaged(_power);
}
};
class Player : public Character {
public:
using Character::Character; // Character 생성자 이용
void damaged(int power) override {
Character::damaged(power);
cout << "끼요옷" << endl;
}
};
class Monster : public Character {
public:
using Character::Character;
void damaged(int power) override {
Character::damaged(power);
cout << "키에엑" << endl;
}
};
int main() {
Player p(200, 100);
Monster m(100, 50);
p.attack(m);
m.attack(p);
}
키에엑
끼요옷
#include <iostream>
using namespace std;
class Character {
public:
virtual ~Character() {
cout << "~Character" << endl;
}
virtual void func() {
cout << "Character func" << endl;
}
};
class Player : public Character {
public:
~Player() {
cout << "~Player" << endl;
}
void func() {
cout << "Player func" << endl;
}
};
int main() {
Character* ch = new Player;
ch->func();
delete ch;
}
// virtual을 붙이지 않으면 ch는 생성자의 타입만으로 함수 호출을 결정하지만
// virtual을 붙이게 되면 ch가 가리키는 타입을 식별하여 함수를 호출한다.
// 그러므로 소멸자는 항상 virtual을 붙여아한다.
Player func
~Player
~Character