1. 캡슐화
: 객체를 필드, 메소를 묶어 실제 구현 내용을 감추는 것
외부 객체는 해당 객체에 대한 구현내용을 알지 못한다
외부에 잘못으로 인한 객체 손상을 막음
2. 상속
: 상위 객체의 필드와 메소드를 하위 객체가 사용할 수 있도록 함
동일한 구현을 줄여주며 쉽고 빠르게 설계가 가능하게 함
3. 다형성
: 하나의 타입에 여러 객체를 대입하므로써 여러 기능을 사용할 수 있게함
// 다형성(Polymorphism)의 사용 예
#include<iostream>
using namespace std;
class Calculator
{
protected:
int m_a;
int m_b;
public:
void SetOprands(int a,int b)
{
m_a = a;
m_b = b;
}
void run()
{
Sum();
Minus();
}
public:
virtual void Sum() {}
virtual void Minus() {}
};
class CalculationPlus : public Calculator
{
void Sum()
{
cout << m_a + m_b << endl;
}
};
class CalculationMinus : public Calculator
{
void Minus()
{
cout<< m_a - m_b << endl;
}
};
class CalculatorDemo {
public:
static void Execute(Calculator *cal)
{
cal->run();
}
};
int main()
{
Calculator *cal = new CalculationPlus();
cal->SetOprands(7, 4);
Calculator *cal2 = new CalculationMinus();
cal2->SetOprands(5,2);
CalculatorDemo::Execute(cal); //static 함수 사용
CalculatorDemo::Execute(cal2);
return 0;
}
- CalculationPlus,CalculationMinus는 Calculator를 상속받는 자식의 클래스이다.
- Calculator *cal = new CalculationPlus() 의 의미는 CaluculationPlus의 클래스는 Calculator타입으로 인스턴스화된다
- 부모의 타입으로 바뀌면 부모의 메소드나 변수를 쓰는 것으로 바뀌는데, 자식의 부모와 동일한 멤버는 자식의 것으로 호출된다.
- CalculatorDemo::Execute(cal) 을 실행하면 cal 인스턴스의 경우 Sum()만 실행되게 되고 Minus()는 실행되지 않는다. cal은 CalculationPlus의 성질을 받은것이니
- CalculatorDemo::Execute(cal2) 을 실행하면 cal2 인스턴스의 경우 Minus()만 실행되게 되고 Sum() 실행되지 않는다.
참고사이트 : https://opentutorials.org/module/516/6127
*참고.1
가상함수의 경우 동적바인딩(바인딩 : 함수호출코드에서 어느위치에 함수를 실행하라는것, 일반함수의 경우 컴파일에서 결정해주는 정적바인딩을 사용하나 가상함수는 프로그램이 실행될때 객체를 결정하므로 런타임시 결정되는 동적바인딩)
virtual void Sum() =0; | 순수 가상 함수 : 필수로 자식이 구현하는 것( 사용예로는 부모 인스턴스로 자식이 정의된 함수 접근 가능) |
virtual void Sum() virtual void Sum() {} // 자식이 구현하도록 함. 이렇게 구현해두면 자식은 필수로 구현안해도 상관이 없다. |
가상 함수 : 자식이 정의할 것을 기대하는 함수 자식에서 구현안해도 상관은 없다 (사용예로는 오버라이딩: 동일하게 구현하여 정의만 바뀔때) |
*참고2
c++에서 static 변수를 사용하려면 static 변수를 사용하는 클래스 외에서 초기화를 하고 사용해야 된다