태그 글목록: virtual functions

[C++ 정리] 객체지향 프로그래밍 및 관련 개념 2015-06-22

객체 지향 프로그래밍(Object-Oriented Programming, OOP) : 프로그래밍 패러다임의 하나로 프로그램을 객체들의 모임으로 보고 개발하는 것이다. 유연하고 변경이 용이하여 대규모 소프트웨어 개발에 많이 사용된다.

장점

* 유연하고 변경이 용이하다. (프로그램의 구조를 파악하기 쉬워 개발과 보수가 간편)

단점

* 지나치게 객체화 하는 것은 실제의 개념과 너무 달라서 이해하기가 쉽지 않아질 수 있다.

특성

* 크게 다음 네가지의 동작 과정이 있다.
  - 클래스(class) : 추상 자료형(빵틀)
  - 객체(object) : 추상 자료형의 인스턴스(빵틀을 통해 만들어진 빵)
  - 메소드(method) : 추상 자료형에 정의된 연산(빵을 자르는 명령)
  - 메시지(message) : 메소드의 호출(빵을 자르는 명령을 실행)
* 클래스는 정보은닉(Data Hiding)을 위해 캡슐화(Encapsulation)를 지향해야 한다.
  : 내부 구현내용은 보이지 않도록 하고 약속된 부분만을 보이도록 지정한다.
  => 새로운 클래스에서 약속되지 않은부분을 추측해서 개발 했을 경우 문제가 발생할 수 있다.
* 기존 클래스의 기능을 상속(Inheritance)받는다.
  : 하위 클래서에서는 기존 기능을 응용해 추가적인 요구사항을 개발할 수 있다.
  => 클래스간의 종속관계를 형성시켜 객체를 조직화할 수 있고 소스코드의 재사용성을 더해준다.
* 2개 이상의 클래스로부터 상속받을 수 있다.(다중상속)
  => 클래스의 상속관계에 혼란을 줄 수 있으므로 주의해야한다.
* 다형성(polymorphism)을 위해 다음과 같은 개념을 사용한다.
  : 객체의 메소드를 여러가지 개념으로 사용 되도록 할 수 있다.
  => 클래스의 상속관계에서 가상함수(Virtual Functions)를 사용
  => 메소드를 오버라이딩(Overriding - 같은 이름의 메소드가 여러 클래스에서 다른기능을 하는것)
     ※ 오버라이딩을 위해 순수가상함수(Pure Virtual Functions)를 정의한다.
     ※ 순수가상함수가 1개 이상 선언된 클래스를 추상클래스(Abstract Class)라 부른다.
  => 메소드를 오버로딩(Overloading - 같은 이름의 메소드가 인자의 갯수나 자료형에 따라서 다른 기능을 하는것)
#include "stdafx.h"
#include <iostream>

using namespace std;

// Ex1> 클래스(Class)의 선언
class Dot
{
public:
	Dot();
	// Ex2> 생성자 Dot을 오버로딩(Overloading) 한다.
	Dot(int x, int y)
	{
		this->x = x;
		this->y = y;
	}
	int x;
	int y;
	// Ex3> 가상함수(Virtual Functions)를 선언한다.
	virtual int Cal()
	{
		return this->x - y;
	}
	// Ex4> 일반 멤버함수를 선언한다.
	void NotVirtual()
	{
		cout << "DOT CALL\n";
	}
	// Ex5> 순수가상함수(Pure Virtual Functions)를 선언한다.
	virtual void PureVirtual() const = 0;
};

// Ex6> Dot 클래스를 상속(Inheritance) 받는다.
class DotA:public Dot
{
public:
	DotA();
	DotA(int x, int y);
	// virtual는 생략가능하다.
	virtual int Cal()
	{
		return this->x + this->y;
	}
	void NotVirtual()
	{
		cout << "DOTA CALL\n";
	}
	virtual void PureVirtual() const
	{
		cout << "DOTA CALL\n";
	}
};
DotA::DotA(int x, int y):Dot(x, y)
{
	cout << "SET DotA\n";
}

class DotB :public Dot
{
public:
	DotB();
	DotB(int x, int y);
	// virtual는 생략가능하다.
	virtual int Cal()
	{
		return this->x * this->y;
	}
	void NotVirtual()
	{
		cout << "DOTB CALL\n";
	}
	virtual void PureVirtual() const
	{
		cout << "DOTB CALL\n";
	}
};
DotB::DotB(int x, int y) :Dot(x, y)
{
	cout << "SET DotB\n";
}

int _tmain(int argc, _TCHAR* argv[])
{
	// 가상함수의 사용
	Dot* dot[2] = {};
	// Ex7> 객체 생성
	dot[0] = new DotA(100, 20);
	dot[1] = new DotB(100, 20);

	cout << "\n######## Virtual Functions ########\n";
	// 가상함수의 사용
	cout << "DotA Result : " << dot[0]->Cal() << "\n";
	cout << "DotB Result : " << dot[1]->Cal() << "\n";

	cout << "\n######## Member Functions ########\n";
	// 일반멤버함수의 사용
	dot[0]->NotVirtual();
	dot[1]->NotVirtual();

	cout << "\n######## Pure Virtual Functions ########\n";
	// 순수가상함수의 사용
	dot[0]->PureVirtual();
	dot[1]->PureVirtual();

	// Ex8> 추상클래스(Abstract Class) 생성
	// 순수가상함수"virtual void PureVirtual() const = 0;"를 선언하므로써 Dot은 추상클래스(Abstract Class)가 되었다.
	// 즉, 추상클래스는 말그대로 추상화된 클래스(구체화 되지않은 클래스)이기 때문에 상속받아 구현을 해야만 사용할 수 있다.
	// Error - 추상클래스를 상속받은 클래스를 생성하지 않고 그냥 생성하였다.
	// Dot dotTest = new Dot(100, 20);

	return 0;
}
Ex1> 클래스(Class) 선언
Ex2> 오버로딩(Overloading)
Ex3> 가상함수(Virtual Functions) 선언
Ex4> 멤버함수 선언
Ex5> 순수가상함수(Pure Virtual Functions) 선언
Ex6> 클래스 상속(Inheritance)
Ex7> 객체(object) 생성
Ex8> 추상클래스(Abstract Class) 생성

object