들어가기 앞서 우선 절차지향,

 

#include <iostream>

using namespace std;
int main()
{
    string car1Name;
    string car1maker;
    int car1maxSpeed;
    car1maxSpeed = 220;
    showSpeed(car1maxSpeed);
    std::cout << car1maxSpeed << std::endl;


}

void showSpeed(int _spd)
{
    std::cout << _spd << std::endl;
}

▲객체 지향이 적용되지 않은 일반적 절차지향 코딩

두번째 자동차, 세번째 자동차를 만들 상황에 놓이면 코드량이 비약적으로 늘어나는 문제점이 있음

 

 

1. 특징만 뽑아서 추상화

#include <iostream>
using namespace std;

//추상화로 특징 추출해냄.
class Car
{
public:
    string Name;
    string maker;
    int maxSpeed;
    void showSpeed() { std::cout << maxSpeed << std::endl; }
private:
};

int main()
{
    Car car1;
    car1.maxSpeed = 220;
    car1.showSpeed();
    car1.maker = "Honda";
}

▲ 특징만 뽑아내어 자동차라는 클래스를 만듦.

실제 존재하는, 혹은 만들고자 하는 대상으로부터 특성, 특징, 주요 행동들만 추출하여 하나에 모으는 것을 추상화라고 함

 

 

아직 문제가 있는데, 해당 클래스로 찍어낼 경우 맴버 변수가 노출되어 있어서 코딩 실수, 안전과는 거리가 멀게 됨

 

 

2. 정보 은닉 및 캡슐화

#include <iostream>
using namespace std;

//추상화로 특징 추출해냄.
class Car
{
private:
    string Name;
    string maker;
    int maxSpeed;  
public:
    void SetMaxSpeed(int _spd) { maxSpeed = _spd; }
    int GetMaxSpeed() { return maxSpeed; }
};

int main()
{
    Car car1;
    car1.SetMaxSpeed(220);
    cout << car1.GetMaxSpeed() << endl;
}

▲ 맴버변수를 프라이빗으로 바꾸어 직접적인 맴버변수 노출을 막고

게터 세터와 같은 함수를 통해야만 접근 할 수 있게 바뀜

 

데이터 구조와 방법을 하나로 묶는것. 함수를 통하여 변수를 건드려야 하는데, 이렇게 외부로부터 정보 보호 해주는건 정보 은닉이라고 함.

 

 

3. 상속성

#include <iostream>
#include <vector>
using namespace std;

//추상화로 특징 추출해냄.
class Car
{
private:
    string Name;
    string maker;
    int maxSpeed;  
public:
    void SetMaxSpeed(int _spd) { maxSpeed = _spd; }
    int GetMaxSpeed() { return maxSpeed; }
    void doWork() { cout << "단순 주행" << endl; }
};

class Tractor
{
private:
    string Name;
    string maker;
    int maxSpeed;
public:
    void SetMaxSpeed(int _spd) { maxSpeed = _spd; }
    int GetMaxSpeed() { return maxSpeed; }
    void doWork() { cout << "추수" << endl; }
};

class Excavator
{
private:
    string Name;
    string maker;
    int maxSpeed;
public:
    void SetMaxSpeed(int _spd) { maxSpeed = _spd; }
    int GetMaxSpeed() { return maxSpeed; }
    void doWork() { cout << "땅파기" << endl; }
};


int main()
{
    Car car1;
    car1.SetMaxSpeed(220);
    cout << car1.GetMaxSpeed() << endl;
}

▲트랙터나 포크레인같은 자동차와 비슷한 클래스를 만들었다면

특징은 비슷한데, 중복된 사항이 많은 클래스들이 많이 생김

 

#include <iostream>
#include <vector>
using namespace std;

//추상화로 특징 추출해냄.
class Car
{
protected:
    string Name;
    string maker;
    int maxSpeed;  
public:
    void SetMaxSpeed(int _spd) { maxSpeed = _spd; }
    int GetMaxSpeed() { return maxSpeed; }
    void doWork() { cout << "단순 주행" << endl; }
};

class Tractor : public Car
{
public:
    void doWork() { cout << "추수" << endl; }
};

class Excavator : public Car
{
public:
    void doWork() { cout << "땅파기" << endl; }
};

int main()
{
    Car car1;
    Tractor tractor;
    Excavator excavator;

    car1.doWork();
    tractor.doWork();
    excavator.doWork();
}

▲상속을 통하여 중복 코드를 줄인 모습

 

자식 클래스가 부모 클래스의 특징을 물려받는것. 중복 코드도 줄일 수 있고, 확장에 유용

 

 

차나, 트렉터등 종류 및 관리해야 할 객체가 늘어나면 다시 코드가 길어지는 문제 발생

 

int main()
{
    Car *car1 = new Car();
    Car *car2 = new Car();
    Car *car3 = new Car();
    Tractor *tractor = new Tractor();
    Tractor *tractor2 = new Tractor();
    Excavator *excavator = new Excavator();
    Excavator *excavator2 = new Excavator();

    vector<Car*> carContainter;
    carContainter.push_back(car1);
    carContainter.push_back(car2);
    carContainter.push_back(car3);
    for (auto eachCar : carContainter)
    {
        eachCar->doWork();
    }
    vector<Tractor*> tractorContainter;
    tractorContainter.push_back(tractor);
    tractorContainter.push_back(tractor2);
    for (auto eachTractor : tractorContainter)
    {
        eachTractor->doWork();
    }
    vector<Excavator*> exContainter;
    exContainter.push_back(excavator);
    exContainter.push_back(excavator2);
    for (auto eachEx : exContainter)
    {
        eachEx->doWork();
    }
}

▲상속받은 제각각의 개체들에게 부여된 기능을 써본 결과, 불필요한 과정반복이 보이기 시작

이럴 때, 다형성을 활용

 

 

4. 다형성

int main()
{
    Car *car1 = new Car();
    Car *car2 = new Car();
    Car *car3 = new Car();
    Tractor *tractor = new Tractor();
    Tractor *tractor2 = new Tractor();
    Excavator *excavator = new Excavator();
    Excavator *excavator2 = new Excavator();

    vector<Car*> vehicleContainter;
    vehicleContainter.push_back(car1);
    vehicleContainter.push_back(car2);
    vehicleContainter.push_back(car3);
    vehicleContainter.push_back(tractor);
    vehicleContainter.push_back(tractor2);
    vehicleContainter.push_back(excavator);
    vehicleContainter.push_back(excavator2);

    for (auto eachVehicle : vehicleContainter)
    {
        eachVehicle->doWork();
    }
}

▲하위 자식객체가 상위 Car형으로 바뀌어 컨테이너에 담긴 모습

필요에 따라, 객체가 자유롭게 형을 바꾸어 활용될 수 있는것을 다형성이라고 부름.

형을 바꾸었긴 하나, 해당 코드를 실행해보면 아직 문제가 있음

 

Car형으로 바꾸어서 같은 컨테이너에 담긴건 좋았으나, Car에 있는 함수가 호출되어 버리는 문제 발생

 

class Car
{
protected:
    string Name;
    string maker;
    int maxSpeed;  
public:
    void SetMaxSpeed(int _spd) { maxSpeed = _spd; }
    int GetMaxSpeed() { return maxSpeed; }
    virtual void doWork() { cout << "단순 주행" << endl; }
};

class Tractor : public Car
{
public:
    virtual void doWork() override{ cout << "추수" << endl; }
};

class Excavator : public Car
{
public:
    virtual void doWork() override { cout << "땅파기" << endl; }
};

▲가상함수인 Virtual 및, 오버라이딩을 통해, 자식객체였을 경우 

이것을 실행하여라 하는 재정의 코드 작성

 

▲형을 바꾸어 관리하여도 본 객체의 행동을 취하는 모습.

 

객체가 다양한 형태를 띌 수 있는 것을 말함. 예를들어 부모 포인터로 자식 객체를 만들수도 있고, 필요시 자식 객체가 부모객체로 모습을 바꾸어 활용될 수도 있음.

'정보들 > 토막지식 관련' 카테고리의 다른 글

깊은 복사 vs 얕은 복사. 그리고 복사 생성자  (0) 2021.03.16
WinAPI 아이콘 바꾸는 방법  (0) 2020.06.23
상대 카메라 설명 영상  (0) 2020.06.23
운영체제 - Round Robin  (0) 2020.06.23
바이트 패딩  (0) 2020.06.23

+ Recent posts