본문 바로가기
카테고리 없음

[C++] 가상 함수 (virtual funciton)

by 까망 하르방 2025. 2. 23.
반응형

가상 멤버 함수 (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

 

[C++] Upcasting

Upcasting• 기반 클래스 포인터로 파생 클래스 객체를 가리킬 수 있다.• 기반 클래스 포인터로는 기반 클래스 멤버만 접근 가능• 파생 클래스 접근하려면 static_cast 필요  [예제] upcasting 이란class

zoosso.tistory.com

 

 

📌 함수 바인딩 (Funciton Binding)

 

[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

반응형

댓글