본문 바로가기
야미스터디/Backend

소프트웨어공학 OOP 참고 공부(2)

by 의정부핵꿀밤 2021. 4. 20.
728x90

저번에 이어서 이번엔 c++에서의 오버라이딩, 동적/정적 바인딩, 가상함수 등에 대해서 정리해보려고 한다.

 

- 정적 바인딩 : 컴파일 시간에 호출할 함수가 결정됨

- 동적 바인딩 : 실행파일을 만들때, 바인딩 되지 않고 보류상태로 있다가 실행될 때 바인딩

- 순수 가상함수 : 상속 받는 클래스에서 반드시 재정의해야 하는 인터페이스

- 일반 가상함수 : 상속받는 클래스에서 구현한다면, 오버라이딩 된 메소드 실행, 그렇지 않으면 부모 클래스에서 정의된 대로 실행

 

순수 가상함수 예시
순수 가상함수 실행

여기서는 animal 클래스를 정의하고 그 안에 showinfo()함수를 virtual 함수로 정의하였다. 여기서는 오버라이딩을 통해 아예 함수를 재정의하여 객체마다 인터페이스는 달라지지 않고 출력 내용만 달라졌다.

 

 

위의 예시로 알 수 있는 장점 : 서로 다른 객체끼리도 인터페이스가 바뀌지 않아 유지보수에 용이하다. 

 

위와 관련된 예시 작성해서 실행해보기! 중간고사 출제 가능성 있음!

 

-----------------------------------------------------------------------------------------------------------------------------------

============================================================================

----------------------------------------------------------------------------------------------------------------------------------

 

자 이제부터 내가 리서치하고 이해한대로 오버로딩, 오버라이딩, 가상함수, 동적바인딩, 정적바인딩을 정리해보려고 한다. 교수님이 시험에 낸다고 하셨으니까 20분만 투자해서 정리하고 중간고사 공부 마저해야게따,,,,

 

이전에는 java를 통해 예시를 들어서 설명했지만 java에는 virtual 함수가 없는 관계로 c++을 통해 예시를 들고 정리해서 이해해보려고 한다.

 

일단 너무 헷갈리니까 오버로딩과 오버라이딩 차이부터 정리하고 시작하자!

 

1) 오버로딩 ⏩ 정의를 새로 만든다는 느낌

  • 메소드 이름이 같아야 한다.
  • 리턴형은 상관 없다.
  • 파라미터는 달라야 한다 - 개수 또는 자료형
  • 같은 클래스의 블록 안에 지원된다.

 

 

2) 오버라이딩 ⏩ 기존에 있는 메소드를 재정의 하는 느낌

  • 오버라이드 하고자 하는 메소드가 상위 클래스에 존재해야 한다.
  • 메소드의 이름이 같아야한다.
  • 메소드의 파라미터의 개수와 데이터의 자료형이 같아야 한다
  • 메소드의 리턴형이 같아야 한다
  • 상위 메소드와 동일하거나 더 구체적인 exeption을 발생시켜야 한다.
  • 상위 메소드와 동일하거나 접근 범위가 넓은 접근 제한자를 사용해야 한다.

아익까 약간 오버로딩은 같은 이름의 함수를 인자들로 구분해서 기능 여러개를 만드는거고, 오버라이딩은 아예 함수 이름이랑 인자까지 완전 똑같이 만들어서 객체마다 다르게 동작하게 하는 느낌? 뭔가 알겠는데 설명이 안되네 

그럼 모르는거니까 계속 정리해!!!!

 

오버라이딩이 약간 아리까리해서 더 찾아보다가 완전 맘에 쏙 드는 정리를 찾았다. 여기서 바인딩, 가상함수까지 싸그리 잡아서 짚고 넘어가보자!

 

가상함수 ( Virtual Function)

이는 오버라이딩, 즉 베이스가 되는 클래스(부모 클래스)에서 정의된 멤버함수를 파생된 클래스(자식 클래스)에서 재정의할 때 사용되는 함수이다.

 

오버라이딩(Overriding)

그럼 여기서 오버라이딩이 무엇이냐!

오버라이딩은 오버로딩과 비슷한 기능을 수행하지만, 함수 원형 자체는 바뀌지 않는다. 즉 모양은 같지만 기능이 바뀌는 것이제!

오버라이딩이 사용되는 함수에서는 virtual 키워드를 사용한다. 그렇다면 왜 virtual을 사용하는가??? 대체 왜????

그는 바로 객체지형의 다형성으로 인해 바인딩 시 문제가 발생할 수 있기 때문이다.

 

다형성(polymorphism)

다형성이란 객체지향 프로그래밍에서 하나의 함수 이름이나 연산자를 여러 목적으로 사용이 가능한 특징을 말한다.

즉, 하나의 클래스나 메소드가 다양한 바익으로 동작이 가능한 것을 의미한다.

우리는 이를 오버라이딩과 오버로딩등을 통해 구현하고 있다. 

이런 다형성 때문에 virtual을 사용하지 않으면 바인딩 시 문제가 발생하는 경우가 있다.

 

바인딩(binding)

우선 바인딩이란 함수를 호출할 때 메모리상에 어느 곳에 있는 함수를 실행하라는 의미로 해석하는 것을 의미한다. 다시 말하자면 호출하는 함수의 주소를 메모리에서 찾아서 찾은 메모리 주소를 컴파일러에게 알려주는 것이다. 

여기에는 정적 바인딩과 동적 바인딩이 있는데 정적 바인딩은 함수 호출 코드가 고정된 메모리 주소로 변환되는 것을 의미한다.

그럼 동적바인딩은 자연스럽게 반대의 의미겠지? 동적 바인딩은 함수가 실행될 떄 결정되는 것이다.

암튼 오버라이딩을 사용할 때 virtual 키워드 없이 오버라이딩을 하게 되면 정적바인딩이 왼다. 따라서 virtual 키워드를 사용하여 오버라이딩을 해줘야 동적 바인딩이 되는 것이다.

왜냐? 가상함수는 프로그램이 실행될 때 객체를 결정하기 때문에 컴파일 시간에 해당 객체를 결정할 수 없다. 그래서 virtual 키워드는 동적 바인딩을 위해 사용하는 것이다. 

(확실하지 않지만 내 뇌피셜에 의하면 정적바인딩을 사용할 경우 오버라이딩으로 작성된 객체는 주소를 부여받지 못해서 실행되지 않기 떄문에 다형성을 만족하지 않는다. 따라서 virtual을 통해 동적 바인딩을 하여 오버라이딩으로 작성된 함수를 실행하는것이다,)

 

오버라이딩을 확인하기 위한 예제

#include<iostream>
using namespace std;

class Base {
    int result;
public:
    virtual void dynamic_binding(int x, int y);
    void static_binding(int x, int y);
};
void Base::dynamic_binding(int x, int y)
{
    result = x + y;
    cout << "Base dynamic bind 결과 : " << result << endl;
}
void Base::static_binding(int x, int y)
{
    result = x + y;
    cout << "Base static bind 결과 : " << result << endl;
}

class Derived : public Base {
    int result;
public:
    virtual void dynamic_binding(int x, int y);
    void static_binding(int x, int y);
};
void Derived::dynamic_binding(int x, int y)
{
    result = x - y;
    cout << "Derived dynamic bind 결과 : " << result << endl;
}
void Derived::static_binding(int x, int y)
{
    result = x + y;
    cout << "Derived static bind 결과 : " << result << endl;
}


int main()
{
    Base* s = new Base();
    Base* d = new Derived();

    s->dynamic_binding(1, 5);
    s->static_binding(2, 7);

    d->dynamic_binding(1, 5);
    d->static_binding(2, 7);


    delete s;
    delete d;
}

이를 실행시키면 아래와 같은 결과를 얻을 수 있다. 

결과

위를 보면 알 수 있듯이 virtual을 사용하지 않은 함수는 실행되지 않았다. 따라서 이런 문제때문에 virtual을 사용하는 것이다. 암튼 오버로딩은 함수 이름만 같고 인자나 데이터 타입을 다르게함으로써 컴파일러가 다른 정의를 찾아서 실행시킬 수 있도록 하는거고, 오버라이딩은 아예 부모 클래스의 정의를 아예 무시하고 새로 정의하는 것이다. 이 때 virtual 키워드를 통해서 동적바인딩을 하여 오버라이딩 기능을 사용하는 것이다. 

 

참고!!

순수 가상 함수(pure virtual function)

순수 가상 함수는 함수의 내용이 정의되지 않고 함수의 선언만 하는 가상함수를 말한다. 즉 그냥 진짜 오버라이딩을 하기 위해서!! 상속관계의 파생클래스에서 재정의를 꼭 해줘야 한다!

그리고 순수가상함수를 하나라도 가지고 있는 클래스를 추상클래스라고 한다. 추상 클래스는 함수의 몸체가 없기 때문에 객체 생성이 불가능하다. 이도 그럴것이 함수 이름만 띡 써있고 내용은 정의되어 있지 않은 순수가상함수가 포함되어있으니까 이로 객체를 만들어도 실행시킬수가 없는 것이다.

 

 

내용 출처는 요 블로그! 정리를 너무 잘해주셔서 보고 이해했다 감삼둥🙇‍♀️🙇‍♀️

blog.naver.com/vjhh0712v/221545003919

 

C++ 가상함수(Virtual Function), 오버라이딩(Overriding), 다형성, 정적바인딩, 동적바인딩

이번 포스팅은 상속을 좀 더 응용하여 효율적이게 사용가능한 기능들을 살펴보겠습니다.먼저 C++의 가장 ...

blog.naver.com

---------------------------------------------------------------------------------------------------------------------------------

요정도면 이해된거 같다. 이제 중간고사 공부해야징~~

728x90

댓글