Skip to content

Latest commit

ย 

History

History

05. Polymorphism

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Polymorphism

Contents

  1. Introduction
  2. Polymorphism ์‚ฌ๋ก€
  3. ํ•ธ๋“ค์˜ ์ž๋ฃŒํ˜•์— ์˜ํ•œ ๋ฉค๋ฒ„ ํ•จ์ˆ˜ ํ˜ธ์ถœ (without Polymorphism)
  4. Polymorphism ๊ตฌํ˜„ (๊ฐ€์ƒ ํ•จ์ˆ˜์— ์˜ํ•œ ๋™์  ๋ฐ”์ธ๋”ฉ)
  5. Abstract Classes and Pure Virtual Functions
  6. Case Study: Payroll System Using Polymorphism

1. Introduction

ํ•จ์ˆ˜ ์˜ค๋ฒ„๋กœ๋”ฉ vs. ํ•จ์ˆ˜ ์˜ค๋ฒ„๋ผ์ด๋”ฉ

ํ•จ์ˆ˜ ์˜ค๋ฒ„๋กœ๋”ฉ (Overloading)

์˜ค๋ฒ„๋กœ๋”ฉ์€ ๊ฐ™์€ ํ•จ์ˆ˜๋ผ๋„ ๋งค๊ฐœ๋ณ€์ˆ˜๋งŒ ๋‹ค๋ฅด๋ฉด ์–ผ๋งˆ๋“ ์ง€ ์ •์˜ํ•˜๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ํ•จ์ˆ˜ ์ด๋ฆ„์ด ๊ฐ™์•„์•ผ ํ•œ๋‹ค.
  • ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ์ž๋ฃŒํ˜•์ด ๋‹ค๋ฅด๊ฑฐ๋‚˜ ๊ฐœ์ˆ˜๊ฐ€ ๋‹ฌ๋ผ์•ผ ํ•œ๋‹ค.
  • ๋ฐ˜ํ™˜ํ˜•์˜ ์ฐจ์ด๋Š” ์˜ค๋ฒ„๋กœ๋”ฉ์˜ ์กฐ๊ฑด์„ ๋งŒ์กฑ์‹œํ‚ค์ง€ ์•Š๋Š”๋‹ค.

ํ•จ์ˆ˜ ์˜ค๋ฒ„๋ผ์ด๋”ฉ (Overriding)

์ƒ์† ๊ด€๊ณ„์— ์žˆ๋Š” ํด๋ž˜์Šค ๊ฐ„์˜ ๊ฐ™์€ ์ด๋ฆ„์˜ ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๋Š” ๊ฒƒ์œผ๋กœ์„œ, ๊ธฐ๋ณธ ํด๋ž˜์Šค์—์„œ ์„ ์–ธ๋œ ํ•จ์ˆ˜์™€ ๊ฐ™์€ ์ด๋ฆ„์˜ ํ•จ์ˆ˜๊ฐ€ ํŒŒ์ƒ ํด๋ž˜์Šค์—์„œ ์žฌ์ •์˜๋˜์–ด ์‚ฌ์šฉ๋˜๋Š” ๊ฒฝ์šฐ ์˜ค๋ฒ„๋ผ์ด๋“œ ๋˜์—ˆ๋‹ค๊ณ  ํ•œ๋‹ค.

  • ์˜ค๋ฒ„๋ผ์ด๋“œ ํ•˜๊ณ ์ž ํ•˜๋Š” ํ•จ์ˆ˜๊ฐ€ ๊ธฐ๋ณธ ํด๋ž˜์Šค์— ์กด์žฌํ•ด์•ผ ํ•œ๋‹ค.
  • ํ•จ์ˆ˜ ์ด๋ฆ„์ด ๊ฐ™์•„์•ผ ํ•œ๋‹ค.
  • ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ๊ฐœ์ˆ˜ ๋ฐ ์ž๋ฃŒํ˜•, ๋ฐ˜ํ™˜ํ˜•์ด ๋™์ผํ•ด์•ผ ํ•œ๋‹ค.

์ƒ์† ๊ณ„์ธต ๊ตฌ์กฐ์—์„œ์˜ ๋‹คํ˜•์„ฑ (polymorphism)

  • ํด๋ž˜์Šค ๊ณ„์ธต ๊ตฌ์กฐ์—์„œ์˜ ๋‹ค์–‘ํ•œ ๊ฐ์ฒด๋“ค์— ๋Œ€ํ•ด์„œ, ๋งˆ์น˜ ๊ฐ์ฒด๋“ค์ด ๊ธฐ๋ฐ˜ ํด๋ž˜์Šค์˜ ๊ฐ์ฒด์ธ ๊ฒƒ์ฒ˜๋Ÿผ ์ฒ˜๋ฆฌ
  • ์ด ๋•Œ, ๊ฐ ๊ฐ์ฒด๋Š” ์ž์‹ ์—๊ฒŒ ์ ํ•ฉํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰
    • ์ฆ‰, ์„œ๋กœ ๋‹ค๋ฅธ ํ˜•์˜ ๊ฐ์ฒด๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰
  • ๊ธฐ์กด์˜ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ  ์ƒˆ๋กœ์šด ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋Š” ํšจ์œจ์ ์ธ ๋ฐฉ๋ฒ•์ž„

๋™์  ๋ฐ”์ธ๋”ฉ Dynamic binding =Late binding =Runtime binding

new ์—ฐ์‚ฐ์ž๋Š” ๋™์ ์œผ๋กœ ๋ฐฐ์—ด์„ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ๋‹ค.

  • 10๊ฐœ์˜ ์ •์ˆ˜ ์›์†Œ๋ฅผ ๊ฐ–๋Š” ๋ฐฐ์—ด์„ ํ• ๋‹น int* gradesArray = new int[10];
  • ๋™์  ํ• ๋‹น ๋ฐฐ์—ด์˜ ํฌ๊ธฐ
    • ํ”„๋กœ๊ทธ๋žจ ๋‚ด์—์„œ ์ •์ˆ˜ ๋ณ€์ˆ˜๋‚˜ ์ •์ˆ˜ ๋ณ€์ˆ˜์˜ ์ˆ˜์‹ ํ‘œํ˜„์„ ํ†ตํ•ด ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ์Œ
    • int* gradesArray = new int[count1+count2];

2. Polymorphism ์‚ฌ๋ก€

์‚ฌ๋ก€: Animal ํด๋ž˜์Šค ๊ณ„์ธต์—์„œ ๋‹คํ˜•์„ฑ ๋™์ž‘

  • Animal ๊ธฐ๋ณธ ํด๋ž˜์Šค์™€ ๋ชจ๋“  ํŒŒ์ƒ ํด๋ž˜์Šค (Fish, Frog, Bird)๋Š” move ํ•จ์ˆ˜๋ฅผ ๊ฐ–๋Š”๋‹ค.
  • ์„œ๋กœ ๋‹ค๋ฅธ ํŒŒ์ƒ ํด๋ž˜์Šค ๊ฐ์ฒด ํฌ์ธํ„ฐ๋“ค์€ Animal* ํ˜•์˜ ํ•ธ๋“ค์— ์ €์žฅ
  • ํ”„๋กœ๊ทธ๋žจ์€ ๊ฐ™์€ ๋ฉ”์‹œ์ง€๋ฅผ (์˜ˆ: move) ๊ฐ Animal ๊ฐ์ฒด์— ์ „๋‹ฌํ•œ๋‹ค. ์ฆ‰, ํ•ธ๋“ค๋กœ move ํ•จ์ˆ˜ ํ˜ธ์ถœ
  • ์ด ๋•Œ, ๊ฐ ๊ฐ์ฒด๋Š” ์ž์‹ ์—๊ฒŒ ์ ๋‹นํ•œ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
    • Fish ๋Š” ์ˆ˜์˜ํ•˜๋ฉฐ move๋ฅผ ์ˆ˜ํ–‰
    • Frog ๋Š” ์ ํ”„ํ•˜๋ฉฐ move๋ฅผ ์ˆ˜ํ–‰
    • Bird ๋Š” ๋‚ ์•„๊ฐ€๋ฉฐ move๋ฅผ ์ˆ˜ํ–‰

ํ•ธ๋“ค์ด๋ž€?

  • ํ•ธ๋“ค์€ ๊ตฌ์ฒด์ ์ธ ์–ด๋–ค ๋Œ€์ƒ์„ ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•œ ์šฉ๋„๋กœ ์“ฐ์ด๋Š” ๋งค๊ฐœ์ฒด์ด๋‹ค.
  • ํ•ธ๋“ค๋กœ์„œ ๋ ˆํผ๋Ÿฐ์Šค ๋ณ€์ˆ˜์™€ ํฌ์ธํ„ฐ ๋ณ€์ˆ˜, ๋ฐ˜๋ณต์ž๊ฐ€ ์—ฌ๊ธฐ์— ํ•ด๋‹นํ•œ๋‹ค.

Polymorphism ๋™์ž‘ ๋ฉ”์ปค๋‹ˆ์ฆ˜

  1. Derived class ๊ฐ์ฒด๋ฅผ base class์˜ ํฌ์ธํ„ฐ/์ฐธ์กฐํ˜• ํ•ธ๋“ค๋กœ ๋ฐ›์Œ
  2. Base class์—์„œ ๊ฐ€์ƒ(virtual) ํ•จ์ˆ˜๋กœ ์„ ์–ธ๋œ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œํ‚ฌ ๋•Œ ๋™์ž‘
  • c++๋Š” ๊ฐ์ฒด๋ฅผ ์‹ค์ œ๋กœ ์ƒ์„ฑํ•œ ํด๋ž˜์Šค (์ฆ‰, derived class)์˜ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œํ‚ค๊ฒŒ ๋จ

  • ํ•ธ๋“ค(handle)์˜ ์ž๋ฃŒํ˜•(์ฆ‰, base class)์˜ ํ•จ์ˆ˜๊ฐ€ ์•„๋‹˜

  • -> virtual function์„ ์ด์šฉํ•˜์—ฌ ๋™์ž‘ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ๊ตฌํ˜„ ๊ฐ€๋Šฅ

3. ํ•ธ๋“ค์˜ ์ž๋ฃŒํ˜•์— ์˜ํ•œ ๋ฉค๋ฒ„ ํ•จ์ˆ˜ ํ˜ธ์ถœ (without Polymorphism)

Virtual ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๋•Œ (without using polymorphism)

  • Base class์˜ ํฌ์ธํ„ฐ ํ•ธ๋“ค์ด base class์˜ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋ฉด
    • ํ•ธ๋“ค์˜ ์ž๋ฃŒํ˜•๊ณผ ์‹ค์ œ ๊ฐ์ฒด์˜ ์ž๋ฃŒํ˜•์ด ๊ฐ™์Œ
    • ํ•ธ๋“ค ์ž๋ฃŒํ˜•์˜ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœ -> base class ํ•จ์ˆ˜ ํ˜ธ์ถœ
  • Derived class์˜ ํฌ์ธํ„ฐ ํ•ธ๋“ค์ด derived class์˜ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋ฉด
    • ํ•ธ๋“ค์˜ ์ž๋ฃŒํ˜•๊ณผ ์‹ค์ œ ๊ฐ์ฒด์˜ ์ž๋ฃŒํ˜•์ด ๊ฐ™์Œ
    • ํ•ธ๋“ค ์ž๋ฃŒํ˜•์˜ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœ -> derived class ํ•จ์ˆ˜ ํ˜ธ์ถœ
  • Base class์˜ ํฌ์ธํ„ฐ ํ•ธ๋“ค์ด derived class์˜ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋ฉด
    • ํ•ธ๋“ค์€ base class์˜ ํฌ์ธํ„ฐ, ์‹ค์ œ ๊ฐ์ฒด๋Š” ํŒŒ์ƒ ํด๋ž˜์Šค์˜ ๊ฐ์ฒด์ž„
    • ํ•ธ๋“ค ์ž๋ฃŒํ˜•์˜ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœ -> base class ํ•จ์ˆ˜ ํ˜ธ์ถœ

๊ฐ€์ƒ ํ•จ์ˆ˜ (virtual function)์˜ ๊ธฐ๋Šฅ

  • virtual ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๋•Œ (w/o using polymorphism)
    • ํ•จ์ˆ˜์˜ ํ˜ธ์ถœ์€ ๊ฐ์ฒด์˜ ํ•ธ๋“ค(handle)์˜ ์ž๋ฃŒํ˜•์— ์˜ํ•ด์„œ ๊ฒฐ์ •๋จ
    • ์ƒ์„ฑ๋œ ๊ฐ์ฒด์˜ ์‹ค์ œ ์ž๋ฃŒํ˜•์ด ์•„๋‹˜
  • virtual ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•  ๋•Œ (using polymorphism)
    • (ํ•ธ๋“ค์˜ ์ž๋ฃŒํ˜•์ด ์•„๋‹Œ) ์‹ค์ œ ๊ฐ์ฒด์˜ ์ž๋ฃŒํ˜•์ด ํ˜ธ์ถœํ•  ๊ฐ€์ƒํ•จ์ˆ˜๋ฅผ ๊ฒฐ์ •ํ•˜๊ฒŒ ๋œ๋‹ค.
    • c++์—์„œ ๊ฐ์ฒด์ง€ํ–ฅ ์„ค๊ณ„์˜ ๋‹คํ˜•์„ฑ(polymorphism) ๊ตฌํ˜„์˜ ๋ฐฉ๋ฒ•์ž„

ํ•ธ๋“ค์˜ ์ž๋ฃŒํ˜•์— ์˜ํ•œ ํ•จ์ˆ˜ ํ˜ธ์ถœ ์˜ˆ์ œ (w/o polymorphism)

CommissionEmployee.h

#ifndef COMMISSIONEMPLOYEE_H
#define COMMISSIONEMPLOYEE_H

#include <string>
using namespace std;

class CommissionEmployee
{
public:
    CommissionEmployee(const string &, const string &, const string &,
                       double = 0.0, double = 0.0);

    void setFirstName(const string &);
    string getFirstName() const;

    void setLastName(const string &);
    string getLastName() const;

    void setSocialSecurityNumber(const string &);
    string getSocialSecurityNumber() const;

    void setGrossSales(double);
    double getGrossSales() const;

    void setCommissionRate(double);
    double getCommissionRate() const;

    double earnings() const;
    void print() const;

private:
    string firstName;
    string lastName;
    string socialSecurityNumber;
    double grossSales;
    double commissionRate;
};

#endif

CommissionEmployee.cpp

#include "CommissionEmployee.h"
#include <iostream>
#include <string>

using namespace std;

CommissionEmployee::CommissionEmployee(const string &first, const string &last, const string &ssn, double sales, double rate)
{
    firstName = first;
    lastName = last;
    socialSecurityNumber = ssn;
    setGrossSales(sales);
    setCommissionRate(rate);
}

double CommissionEmployee::earnings() const
{
    return commissionRate * grossSales;
}

double CommissionEmployee::getCommissionRate() const
{
    return commissionRate;
}

string CommissionEmployee::getFirstName() const
{
    return firstName;
}

double CommissionEmployee::getGrossSales() const
{
    return grossSales;
}

string CommissionEmployee::getLastName() const
{
    return lastName;
}

string CommissionEmployee::getSocialSecurityNumber() const
{
    return socialSecurityNumber;
}

void CommissionEmployee::print() const
{
    cout << "commission employee: "
         << getFirstName() << ' ' << getLastName() << endl
         << "social security number: " << getSocialSecurityNumber() << endl
         << "gross sales: " << getGrossSales() << endl
         << "commission rate: " << getCommissionRate() << endl;
}

void CommissionEmployee::setCommissionRate(double rate)
{
    commissionRate = (rate > 0.0 && rate < 1.0) ? rate : 0;
}

void CommissionEmployee::setFirstName(const string &first)
{
    firstName = first;
}

void CommissionEmployee::setGrossSales(double sales)
{
    grossSales = sales < 0.0 ? 0 : sales;
}

void CommissionEmployee::setLastName(const string &last)
{
    lastName = last;
}

void CommissionEmployee::setSocialSecurityNumber(const string &ssn)
{
    socialSecurityNumber = ssn;
}

BasePlusCommissionEmployee.h

#ifndef BASEPLUSCOMMISSIONEMPLOYEE_H
#define BASEPLUSCOMMISSIONEMPLOYEE_H

#include <string>
#include "CommissionEmployee.h"

using namespace std;

class BasePlusCommissionEmployee : public CommissionEmployee
{
private:
    double baseSalary;

public:
    BasePlusCommissionEmployee(const string &, const string &, const string &,
                               double = 0.0, double = 0.0, double = 0.0);

    void setBaseSalary(double);
    double getBaseSalary() const;

    void print() const;
    double earnings() const;
};

#endif

BasePlusCommissionEmployee.cpp

#include "BasePlusCommissionEmployee.h"
#include <iostream>
#include <string>
#include "CommissionEmployee.h"

using namespace std;

BasePlusCommissionEmployee::BasePlusCommissionEmployee(const string &first, const string &last, const string &ssn, double sales, double rate, double salary)
    : CommissionEmployee(first, last, ssn, sales, rate)
{
    setBaseSalary(salary);
}

double BasePlusCommissionEmployee::earnings() const
{
    return getBaseSalary() + CommissionEmployee::earnings();
}

double BasePlusCommissionEmployee::getBaseSalary() const
{
    return baseSalary;
}

void BasePlusCommissionEmployee::print() const
{
    cout << "base-salaried ";
    CommissionEmployee::print();
    cout << "base salary: " << baseSalary << endl;
}

void BasePlusCommissionEmployee::setBaseSalary(double salary)
{
    baseSalary = salary < 0.0 ? 0 : salary;
}

main.cpp

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2021-12-07 แ„‹แ…ฉแ„’แ…ฎ 10 36 17

> print() ํ•จ์ˆ˜๋ฅผ virtual๋กœ ์„ ์–ธํ–ˆ์„ ๋•Œ์™€ ์•„๋‹ ๋•Œ์˜ ์ฐจ์ด์ (์œ„์—์„œ * ๋ถ€๋ถ„)์„ ํ™•์ธํ•  ๊ฒƒ

ํŒŒ์ƒ ํด๋ž˜์Šค์˜ ํฌ์ธํ„ฐ๊ฐ€ ๊ธฐ๋ณธ ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ฌ ๋•Œ

  • C++ ์ปดํŒŒ์ผ๋Ÿฌ์—์„œ ์—๋Ÿฌ ์ƒ์„ฑ
    • CommissionEmployee (๊ธฐ๋ณธ ํด๋ž˜์Šค ๊ฐ์ฒด) is not a BasePlusCommissionEmployee (ํŒŒ์ƒ ํด๋ž˜์Šค ๊ฐ์ฒด)
  • ๋งŒ์•ฝ ์ด๊ฒƒ์ด ํ—ˆ์šฉ๋œ๋‹ค๋ฉด, ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํŒŒ์ƒ ํด๋ž˜์Šค์˜ ๋ฉค๋ฒ„์— ์ ‘๊ทผํ•  ๊ฒƒ์ด๋‹ค.
    • ์ „ํ˜€ ์—‰๋šฑํ•œ ๋ฐ์ดํ„ฐ์— ์‚ฌ์šฉ๋˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ๋‚ด์šฉ์„ ๋ณ€๊ฒฝํ•˜๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒ ๊ฐ€๋Šฅ

์˜ˆ์ œ (ํŒŒ์ƒ ํด๋ž˜์Šค์˜ ํฌ์ธํ„ฐ๊ฐ€ ๊ธฐ๋ณธ ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ฌ ๋•Œ)

main.cpp
#include "CommissionEmployee.h"
#include "BasePlusCommissionEmployee.h"

int main()
{
    CommissionEmployee commissionEmployee(
        "Sue", "Jones", "222-22-2222", 10000, .06);
    BasePlusCommissionEmployee *basePlusCommissionEmployeePtr = 0;

    // aim derived-class pointer at base-class object
    // Error: a CommissionEmployee is not a BasePlusCommissionEmployee
    basePlusCommissionEmployeePtr = &commissionEmployee;

    return 0;
}
Error Message

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2021-12-07 แ„‹แ…ฉแ„’แ…ฎ 10 44 04

๊ธฐ๋ณธ ํด๋ž˜์Šค์˜ ํฌ์ธํ„ฐ๊ฐ€ ํŒŒ์ƒํด๋ž˜์Šค ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ฌ ๋•Œ

  • ๊ธฐ๋ณธ ํด๋ž˜์Šค์— ์กด์žฌํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๊ธฐ๋ณธ ํด๋ž˜์Šค์˜ ๊ธฐ๋Šฅ์ด ์ˆ˜ํ–‰
  • ํŒŒ์ƒ ํด๋ž˜์Šค์—๋งŒ ์กด์žฌํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์ปดํŒŒ์ผ ์—๋Ÿฌ ๋ฐœ์ƒ
    • ๊ธฐ๋ณธ์ ์œผ๋กœ ํŒŒ์ƒ ํด๋ž˜์Šค์˜ ๋ฉค๋ฒ„๋Š” ๊ธฐ๋ณธ ํด๋ž˜์Šค์˜ ๊ฐ์ฒด ํฌ์ธํ„ฐ๋กœ๋ถ€ํ„ฐ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋‹ค.
    • ์–ต์ง€๋กœ downcasting์„ ์ด์šฉํ•˜๋ฉด ๊ฐ€๋Šฅ

4. Polymorphism ๊ตฌํ˜„ (๊ฐ€์ƒ ํ•จ์ˆ˜์— ์˜ํ•œ ๋™์  ๋ฐ”์ธ๋”ฉ)

๊ฐ€์ƒ ํ•จ์ˆ˜ (Virtual Function) ์‚ฌ์šฉ์— ์˜ํ•œ ๋™์  ๋ฐ”์ธ๋”ฉ

  • ์ผ๋ฐ˜์ ์ธ ๊ฒฝ์šฐ (w/o virtual function)
    • ํ•ธ๋“ค(handle)์ด ์–ด๋– ํ•œ ํด๋ž˜์Šค ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ• ์ง€ ๊ฒฐ์ •ํ•œ๋‹ค.
  • ๊ฐ€์ƒ ํ•จ์ˆ˜ ์‚ฌ์šฉ์˜ ๊ฒฝ์šฐ
    • ํ•ธ๋“ค์˜ ์ž๋ฃŒํ˜•์ด ์•„๋‹Œ, ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋Š” ๊ฐ์ฒด์˜ ์‹ค์ œ ์ž๋ฃŒํ˜•์ด ๊ฐ€์ƒ ํ•จ์ˆ˜์˜ ์–ด๋–ค ๊ตฌํ˜„์„ ์‚ฌ์šฉํ• ์ง€ ๊ฒฐ์ •ํ•˜๊ฒŒ ๋œ๋‹ค.
    • ํ”„๋กœ๊ทธ๋žจ์ด ๋™์ ์œผ๋กœ (์ปดํŒŒ์ผ ์‹œ๊ฐ„์ด ์•„๋‹Œ ์‹คํ–‰์‹œ๊ฐ„์—) ์–ด๋–ค ํด๋ž˜์Šค์˜ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ• ์ง€ ๊ฒฐ์ •ํ•œ๋‹ค.
      • ๋™์  ๋ฐ”์ธ๋”ฉ (dynamic binding) ์ด๋ผ๊ณ  ํ•จ

๊ฐ€์ƒ ํ•จ์ˆ˜ (Virtual Function) ์„ ์–ธ

  • ๊ธฐ๋ณธ ํด๋ž˜์Šค ์„ ์–ธ์—์„œ virtual ํ‚ค์›Œ๋“œ๋ฅผ ํ•จ์ˆ˜ ์›ํ˜• ์•ž์— ๋ถ™์ž„์œผ๋กœ์จ ๊ฐ€์ƒํ•จ์ˆ˜๋ฅผ ์„ ์–ธ
    • ์˜ˆ) virtual void print()
  • ํŒŒ์ƒ ํด๋ž˜์Šค๋Š” ๊ธฐ๋ณธ ํด๋ž˜์Šค์˜ ๊ฐ€์ƒ ํ•จ์ˆ˜๋ฅผ override ํ•œ๋‹ค.
  • ๊ธฐ๋ณธ ํด๋ž˜์Šค์˜ ๊ฐ€์ƒ ํ•จ์ˆ˜๋Š”, ๋ชจ๋“  ๊ณ„์ธต์˜ ํŒŒ์ƒ ํด๋ž˜์Šค์—์„œ ์—ญ์‹œ virtual ํ•จ์ˆ˜์ด๋‹ค

์ •์  ๋ฐ”์ธ๋”ฉ๊ณผ ๋™์  ๋ฐ”์ธ๋”ฉ

์ •์  ๋ฐ”์ธ๋”ฉ (static binding)

ํŠน์ • ๊ฐ์ฒด๊ฐ€ dot operator๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉค๋ฒ„ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด, virtual ์—ฌ๋ถ€์— ๊ด€๊ณ„์—†์ด ํ˜ธ์ถœ๋œ ํ•จ์ˆ˜๋Š” (ํ•ธ๋“ค์— ์˜ํ•ด) ์ปดํŒŒ์ผ ์‹œ๊ฐ„์— ๊ฒฐ์ •๋œ๋‹ค.

๋™์  ๋ฐ”์ธ๋”ฉ (dynamic binding)

๊ฐ€์ƒํ•จ์ˆ˜์˜ ๋™์  ๋ฐ”์ธ๋”ฉ์€ ํฌ์ธํ„ฐ ๋˜๋Š” ์ฐธ์กฐํ˜•์˜ ํ•ธ๋“ค์—์„œ๋งŒ ์ด๋ฃจ์–ด์ง„๋‹ค.

๋™์  ๋ฐ”์ธ๋”ฉ ์˜ˆ์ œ

CommissionEmployee.h

#ifndef COMMISSION_EMPLOYEE_H
#define COMMISSION_EMPLOYEE_H

#include <string>

using namespace std;

class CommissionEmployee
{
public:
    CommissionEmployee(const string &, const string &, const string &,
                       double = 0.0, double = 0.0);

    void setFirstName(const string &);
    string getFirstName() const;

    void setLastName(const string &);
    string getLastName() const;

    void setSocialSecurityNumber(const string &);
    string getSocialSecurityNumber() const;

    void setGrossSales(double);
    double getGrossSales() const;

    void setCommissionRate(double);
    double getCommissionRate() const;

    virtual double earnings() const;
    virtual void print() const;

private:
    // protected:
    string firstName;
    string lastName;
    string socialSecurityNumber;
    double grossSales;
    double commissionRate;
};

#endif

CommissionEmployee.h

#include <iostream>
using std::cout;

#include "CommissionEmployee.h"

CommissionEmployee::CommissionEmployee(
    const string &first, const string &last, const string &ssn,
    double sales, double rate)
{
    firstName = first;
    lastName = last;
    socialSecurityNumber = ssn;
    setGrossSales(sales);
    setCommissionRate(rate);
}

void CommissionEmployee::setFirstName(const string &first)
{
    firstName = first;
}

string CommissionEmployee::getFirstName() const
{
    return firstName;
}

void CommissionEmployee::setLastName(const string &last)
{
    lastName = last;
}

string CommissionEmployee::getLastName() const
{
    return lastName;
}

void CommissionEmployee::setSocialSecurityNumber(const string &ssn)
{
    socialSecurityNumber = ssn;
}

string CommissionEmployee::getSocialSecurityNumber() const
{
    return socialSecurityNumber;
}

void CommissionEmployee::setGrossSales(double sales)
{
    grossSales = (sales < 0.0) ? 0.0 : sales;
}

double CommissionEmployee::getGrossSales() const
{
    return grossSales;
}

void CommissionEmployee::setCommissionRate(double rate)
{
    commissionRate = (rate > 0.0 && rate < 1.0) ? rate : 0.0;
}

double CommissionEmployee::getCommissionRate() const
{
    return commissionRate;
}

double CommissionEmployee::earnings() const
{
    return commissionRate * grossSales;
}

void CommissionEmployee::print() const
{
    cout << "commission employee: " << firstName << ' ' << lastName
         << "\nsocial security number: " << socialSecurityNumber
         << "\ngross sales: " << grossSales
         << "\ncommission rate: " << commissionRate;
}

BasePlusCommissionEmployee.h

#ifndef BASE_PLUS_COMMISSION_EMPLOYEE_H
#define BASE_PLUS_COMMISSION_EMPLOYEE_H

#include <string>
#include "CommissionEmployee.h"

using namespace std;

class BasePlusCommissionEmployee : public CommissionEmployee
{
public:
    BasePlusCommissionEmployee(const string &, const string &, const string &,
                               double = 0.0, double = 0.0, double = 0.0);

    void setBaseSalary(double);
    double getBaseSalary() const;

    virtual double earnings() const;
    virtual void print() const;

private:
    double baseSalary;
};

#endif

BasePlusCommissionEmployee.cpp

#include <iostream>
using std::cout;

#include "BasePlusCommissionEmployee.h"

BasePlusCommissionEmployee::BasePlusCommissionEmployee(
    const string &first, const string &last, const string &ssn,
    double sales, double rate, double salary)
    : CommissionEmployee(first, last, ssn, sales, rate)
{
    setBaseSalary(salary);
}

void BasePlusCommissionEmployee::setBaseSalary(double salary)
{
    baseSalary = (salary < 0.0) ? 0.0 : salary;
}

double BasePlusCommissionEmployee::getBaseSalary() const
{
    return baseSalary;
}

double BasePlusCommissionEmployee::earnings() const
{
    // double tempCommissionRate = getCommissionRate();
    // double tempGrossSales = getGrossSales();
    // return baseSalary + (tempCommissionRate * tempGrossSales);
    return baseSalary + (getCommissionRate() * getGrossSales());
}

void BasePlusCommissionEmployee::print() const
{

    cout << "base-salaried commission emplyee: " << getFirstName() << ' '
         << getLastName() << "\nsocial security number: " << getSocialSecurityNumber()
         << "\ngross sales: " << getGrossSales()
         << "\ncommission rate: " << getCommissionRate()
         << "\nbase salary: " << baseSalary;
}

driver

#include <iostream>
#include <iomanip>

#include "BasePlusCommissionEmployee.h"
#include "CommissionEmployee.h"

using namespace std;

int main()
{
    CommissionEmployee commissionEmployee(
        "Sue", "Jones", "222-22-2222", 10000, 0.6);

    CommissionEmployee *commissionEmployeePtr = 0;

    BasePlusCommissionEmployee basePlusCommissionEmployee(
        "Bob", "Lewis", "333-33-3333", 5000, 0.04, 300);

    BasePlusCommissionEmployee *basePlusCommissionEmployeePtr = 0;

    cout << fixed << setprecision(2);

    cout << "Invoking print function on base-class and derived-class "
         << "\nobjects with static binding\n\n";
    commissionEmployee.print();
    cout << "\n\n";
    basePlusCommissionEmployee.print();

    cout << "\n\n\nInvoking print function on base-class and "
         << "derived-class \nobjects with dynamic binding:";

    commissionEmployeePtr = &commissionEmployee;
    cout << "\n\nCalling virtual function print with base-class pointer"
         << "\n to base-class object invokes base-class "
         << "print function:\n\n";
    commissionEmployeePtr->print();

    basePlusCommissionEmployeePtr = &basePlusCommissionEmployee;
    cout << "\n\nCalling virtual function print with derived-class "
         << "pointer\nto derived-class object invokes derived-class "
         << "print function:\n\n";
    basePlusCommissionEmployeePtr->print();

    commissionEmployeePtr = &basePlusCommissionEmployee;
    cout << "\n\nCalling virtual function print with base-class pointer "
         << "\nto derived-class object invokes derived-class "
         << "print function:\n\n";

    commissionEmployeePtr->print();
    cout << endl;
    return 0;
}

์‹คํ–‰ ๊ฒฐ๊ณผ

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2021-12-07 แ„‹แ…ฉแ„’แ…ฎ 10 51 54

5. Abstract Classes and Pure Virtual Functions

์ถ”์ƒ ํด๋ž˜์Šค (Abstract Class)

  • Client๊ฐ€ ์‹ค์ œ๋กœ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š๋Š” (๋ถˆ์™„์ „ํ•œ) ํด๋ž˜์Šค
    • ํŒŒ์ƒ ํด๋ž˜์Šค๋“ค์˜ ๊ณตํ†ต์ ์ด๊ณ  ์ถ”์ƒ์ ์ธ ํŠน์ง•๋งŒ ์ •์˜ํ•จ
      • -> ํŒŒ์ƒ ํด๋ž˜์Šค๊ฐ€ โ€œ๋น ์ง„ ๋ถ€๋ถ„๏ผ‚์„ ์ •์˜ํ•ด์•ผ ํ•œ๋‹ค.
    • ์‹ค์ œ ๊ฐ์ฒด๋ฅผ ์ •์˜ ํ•˜๊ธฐ์— ๋„ˆ๋ฌด ํฌ๊ด„์ ์ด๋‹ค.
  • ์ผ๋ฐ˜์ ์œผ๋กœ ๊ธฐ๋ณธ ํด๋ž˜์Šค๋กœ ์‚ฌ์šฉ๋˜๋ฉฐ, ์ถ”์ƒ ๊ธฐ๋ณธ ํด๋ž˜์Šค (abstract base class)๋ผ๊ณ  ๋ถˆ๋ฆฐ๋‹ค.
    • ๋‹ค๋ฅธ ํด๋ž˜์Šค, ์ฆ‰ ๊ตฌ์ฒด์ ์ธ ํŒŒ์ƒ ํด๋ž˜์Šค (concrete class)์— ์ƒ์†๋  ์ˆ˜ ์žˆ๋Š” ์ ํ•ฉํ•œ ๊ธฐ๋ณธ ํด๋ž˜์Šค๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ์กด์žฌ

์ˆœ์ˆ˜ virtual ํ•จ์ˆ˜ (Pure Virtual Function)

  • Pure virtual function์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ทธ ํด๋ž˜์Šค๋Š” ์ถ”์ƒ ํด๋ž˜์Šค๊ฐ€ ๋จ
    • Virtual void draw() const =0;
  • ํ•จ์ˆ˜ ๊ตฌํ˜„์„ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š”๋‹ค. (์œ„ ์˜ˆ์ œ์™€ ๊ฐ™์€ ์›ํ˜•๋งŒ ์กด์žฌ)
    • ๋ชจ๋“  ๊ตฌ์ฒด ํŒŒ์ƒ ํด๋ž˜์Šค๋Š” ๊ธฐ๋ณธ ํด๋ž˜์Šค์˜ ๋ชจ๋“  pure virtual function์„ ์žฌ์ •์˜(override)ํ•˜๊ณ  ๊ตฌ์ฒด์  ๊ตฌํ˜„์„ ์ œ๊ณตํ•ด์•ผ ํ•จ
      • -> ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ํŒŒ์ƒ ํด๋ž˜์Šค ๋˜ํ•œ ์ถ”์ƒ ํด๋ž˜์Šค๊ฐ€ ๋œ๋‹ค.
  • ๊ธฐ๋ณธ ํด๋ž˜์Šค์—์„œ ๋ฉค๋ฒ„ ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด ๋ฌด์˜๋ฏธํ•  ๋•Œ ์‚ฌ์šฉ๋จ
    • ์‹ค์ œ ๊ตฌํ˜„์€ ๊ตฌ์ฒดํ™”๋œ ํŒŒ์ƒ ํด๋ž˜์Šค์—์„œ ์ด๋ฃจ์–ด ์ง

์ถ”์ƒ ๊ธฐ๋ณธ ํด๋ž˜์Šค์˜ ๋‹คํ˜•์„ฑ์—์˜ ์ด์šฉ

  • ํฌ์ธํ„ฐ ๋˜๋Š” ์ฐธ์กฐํ˜• ๊ฐ์ฒด๋ฅผ ์„ ์–ธํ•˜์—ฌ (์ฆ‰, ๊ฐ์ฒด ์ƒ์„ฑ ์–ด์ด ํ•ธ๋“ค๋งŒ ์ƒ์„ฑ) ์ถ”์ƒ ๊ธฐ๋ณธ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ํŒŒ์ƒ๋œ ์–ด๋– ํ•œ ๊ตฌ์ฒด ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ผ๋„ ๊ฐ€๋ฆฌํ‚ฌ ์ˆ˜ ์žˆ์Œ
    • ํ”„๋กœ๊ทธ๋žจ์€ ์ผ๋ฐ˜์ ์œผ๋กœ ์ด๋Ÿฌํ•œ ํฌ์ธํ„ฐ๋‚˜ ์ฐธ์กฐํ˜•์„ ์ด์šฉํ•˜์—ฌ ํŒŒ์ƒ ํด๋ž˜์Šค ๊ฐ์ฒด์˜ ๋‹คํ˜•์„ฑ์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋‹คํ˜•์„ฑ์€ ๊ณ„์ธตํ™”๋œ ์†Œํ”„ํŠธ์›จ์–ด ์‹œ์Šคํ…œ์˜ ๊ตฌํ˜„์— ํŠนํžˆ ํšจ์œจ์ 
    • ์˜ˆ) ์—ฌ๋Ÿฌ ๋‹ค๋ฅธ ์žฅ์น˜(device)์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ฑฐ๋‚˜ ์“ธ ๋•Œ
      • ์ถ”์ƒ ํด๋ž˜์Šค๋Š” ๊ณตํ†ต์ ์ธ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ pure virtual function์œผ๋กœ ์ œ๊ณตํ•˜๊ณ , ์‹ค์ œ ์ž…์ถœ๋ ฅ์€ ํŒŒ์ƒ ํด๋ž˜์Šค์—์„œ ์žฌ์ •์˜ํ•œ ํ•จ์ˆ˜๊ฐ€ ๋‹ด๋‹น

๊ธฐ์กด Employee ํด๋ž˜์Šค ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ฐœ์„ 

  • ์ถ”์ƒ ํด๋ž˜์Šค Employee๋Š” ์ผ๋ฐ˜์ ์ธ โ€˜์ข…์—…์›โ€™์˜ ํŠน์ง•์„ ํ‘œํ˜„
    • ๊ณ„์ธต ๊ตฌ์กฐ์˜ โ€œinterfaceโ€๋ฅผ ์„ ์–ธ
    • ๊ฐ ์ข…์—…์›์˜ ๊ณตํ†ต ์†์„ฑ ์„ ์–ธ
      • -> first name, last name, social security number
  • ์ˆ˜์ž…(earnings)์˜ ๊ณ„์‚ฐ ๋ฐฉ๋ฒ• ๋ฐ ๊ฐ์ฒด ์ •๋ณด์˜ ์ถœ๋ ฅ ๋ฐฉ๋ฒ•์€ ๊ตฌ์ฒด ํŒŒ์ƒ ํด๋ž˜์Šค ๋งˆ๋‹ค ๋ชจ๋‘ ๋‹ค๋ฆ„

๊ธฐ์กด Employee ํด๋ž˜์Šค ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ฐœ์„ 

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2021-12-07 แ„‹แ…ฉแ„’แ…ฎ 10 56 17

6. Case Study: Payroll System Using Polymorphism