※ 클래스 중에서는 객체생성을 목적으로 정의되지 않는 클래스도 존재한다. !!

따라서 다음과 같은 문장이 만들어진다면 이는 프로그래머의 실수가 틀림없다.

Employee* emp = new Employee("sadf");


하지만, 이는 문법적으로 아무런 문제가 없는 문장이기 때문에, 이러한 실수는 컴파일러에 의해서 발견되지 않는다. 

따라서 이러한 경우 가상함수를 "순수 가상함수"로 선언하여 객체의 생성을 문법적으로 막는 것이 좋다. 


class Employee

{

private:

char name[100];


public:

virtual int GetPay(void) const = 0;        // 순수 가상함수.

virtual void ShowAll(void) const = 0;    // 순수 가상함수.

};


"순수 가상함수"란 "함수의 몸체가 정의되지 않은 함수"를 의미한다. 그리고 이를 표현하기 위해 위에서 보이듯 '0의 대입' 을 표시한다. 그런데 이것은 0의 대입을 의미하는 게 아니고, "명시적으로 몸체를 정의하지 않았음" 을 컴파일러에게 알리는 것이다. 

따라서 컴파일러는 이 부분에서 함수의 몸체가 정의되지 않았다고 컴파일 오류를 일으키지 않는다. 그러나 Employee 클래스는 순수 가상함수를 지닌, 완전하지 않은 클래스가 되기 때문에 다음과 같이 객체를 생성하려 들면 컴파일 에러가 발생한다. 


Employee * emp = new Employee("asdf");     // error 발생!!


이렇게 순수 가상함수를 이용하면 두 가지 이점을 얻을 수 있다. 

하나는, 잘못된 객체의 생성을 막을 수 있다. 

또 하나는 보다 명확히 명시하는 효과를 얻을 수 있다. 


이렇듯 하나 이상의 멤버함수를 순수 가상함수로 선언한 클래스를 가리켜 "추상 클래스(Abstract Class)" 라 한다. 

이는 완전하지 않은, 그래서 객체생성이 불가능한 클래스라는 의미를 지닌다.



- 가상함수와 순수 가상함수 그리고 추상 클래스의 대한 예제 -


#include <iostream>

#include <cstring>

using namespace std;


namespace RISK_LEVEL

{

enum

{

RISK_A = 30,

RISK_B = 20,

RISK_C = 10

};

}


class Employee        // 추상 클래스

{

private:

char name[100];

public:

Employee(char* name)

{

strcpy(this->name, name);

}

void ShowYourName(void) const

{

cout<<"name: "<<name<<endl;

}

virtual int GetPay(void) const = 0; //순수 가상함수

virtual void ShowSalaryInfo(void) const = 0; //순수 가상함수

};


class PermanentWorker :public Employee

{

private:

int salary;

public:

PermanentWorker(char* name, int money)

:Employee(name), salary(money)

{ }

virtual int GetPay(void) const

{

return salary;

}

virtual void ShowSalaryInfo(void) const

{

ShowYourName();

cout<<"salary: "<<GetPay()<<endl<<endl;

}

};


class TemporaryWorker :public Employee

{

private:

int workTime;

int payPerHour;

public:

TemporaryWorker(char* name, int pay)

:Employee(name), payPerHour(pay), workTime(0)

{ }

void AddworkTime(int time)

{

workTime += time;

}

int GetPay(void) const

{

return workTime * payPerHour;

}

void ShowSalaryInfo(void) const

{

ShowYourName();

cout<<"salary: "<<GetPay()<<endl<<endl;

}

};


class SalesWorker :public PermanentWorker

{

private:

int salesResult;

double bonusRatio;

public:

SalesWorker(char* name, int money, double ratio)

:PermanentWorker(name, money), bonusRatio(ratio), salesResult(0)

{ }

void AddSalesResult(int value)

{

salesResult += value;

}

int GetPay(void) const

{

return PermanentWorker::GetPay() + (int)(salesResult*bonusRatio);

}

void ShowSalaryInfo(void) const

{

ShowYourName();

cout<<"salary: "<<GetPay()<<endl;

}

};


class ForeignSalesWorker :public SalesWorker

{

private:

const int riskPay;

public:

ForeignSalesWorker(char* name, int money, double ratio, int riskPay)

:SalesWorker(name, money, ratio), riskPay(riskPay)

{ }


int GetRisk(void) const

{

return (int)(SalesWorker::GetPay() * (riskPay/100.0));

}

int GetPay(void) const

{

return SalesWorker::GetPay();

}

void ShowSalaryInfo(void) const

{

SalesWorker::ShowSalaryInfo();

cout<<"risk pay: "<<GetRisk()<<endl;

cout<<"sum: "<<GetPay() + GetRisk()<<endl<<endl;

}

};


class EmployeeHandler

{

private:

Employee* empList[50];

int empNum;

public:

EmployeeHandler()

:empNum(0)

{ }

void AddEmployee(Employee* emp)

{

empList[empNum++] = emp;

}

void ShowAllSalaryInfo(void) const

{

for(int i=0; i<empNum; i++)

empList[i]->ShowSalaryInfo();

}

void ShowTotalSalary(void) const

{

int sum = 0;


for(int i=0; i<empNum; i++)

sum += empList[i]->GetPay();


cout<<"salary sum: "<<sum<<endl;

}

~EmployeeHandler()

{

for(int i=0; i<empNum; i++)

delete empList[i];

}

};


int main(void)

{

EmployeeHandler handler;


ForeignSalesWorker * fseller1 = new ForeignSalesWorker("Hong", 1000, 0.1, RISK_LEVEL::RISK_A);

fseller1->AddSalesResult(7000);

handler.AddEmployee(fseller1);


ForeignSalesWorker * fseller2 = new ForeignSalesWorker("Yoon", 1000, 0.1, RISK_LEVEL::RISK_B);

fseller2->AddSalesResult(7000);

handler.AddEmployee(fseller2);


ForeignSalesWorker * fseller3 = new ForeignSalesWorker("Lee", 1000, 0.1, RISK_LEVEL::RISK_C);

fseller3->AddSalesResult(7000);

handler.AddEmployee(fseller3);


handler.ShowAllSalaryInfo();


return 0;

'Programming > C++' 카테고리의 다른 글

참조자의 참조 가능성  (0) 2012.08.20
가상 소멸자(Virtual Destructor)  (0) 2012.08.20
가상 함수 (Virtual Function)  (0) 2012.08.19
상속과 다형성  (0) 2012.06.23
Control 클래스 & Entity 클래스  (0) 2012.06.22
Posted by scii
: