C++

[C++] 42SEOUL CPP04 개념 공부하기

madylin 2023. 7. 28. 15:14
반응형

(42Seoul의 CPP04 과제를 진행하며 공부한 내용을 작성한 TIL을 정리한 글 입니다.)


개념 공부📓

가상 함수

  • 가상함수는 ‘virtual’ 키워드를 사용하여 선언한 함수를 의미
  • 가상 함수 테이블은 대체로 아래 순서로 구현됨
    • ‘virtual’ 키워드를 사용하여 가상 함수 선언
    • 클래스에 대한 가상 함수 테이블을 생성함. 가상 함수 테이블은 가상 함수들에 대한 포인터들의 배열
    • 객체에 가상 함수 테이블 포인터를 추가하여, 해당 클래스의 가상함수 테이블을 가리키게 함
    • 가상함수 호출 시, 해당 클래스의 가상 함수 테이블 포인터를 따라가 적절한 가상 함수를 찾아 호출

가상 소멸자

  • 클래스 상속 시, 해당 클래스의 소멸자도 가상 소멸자로 선언해야 함
  • 가상 소멸자로 선언하지 않으면, 해당 클래스를 동적으로 할당하고 삭제 시, 메모리 누수나 undefined behavior 문제가 발생할 수 있음
  • 부모클래스에서 가상 소멸자로 선언되지 않는다면, 자식 클래스의 객체를 가리키는 포인터가 삭제될 때 부모 클래스의 소멸자만 호출됨. 자식 클래스의 소멸자는 호출되지 않아 메모리 누수 발생함

const Animal* j = new Dog();

  • 위 상황은 업캐스팅(Upcasting) 이라고 하며, 파생 클래스의 객체를 기본 클래스의 포인터 또는 참조형으로 변환하는 것
  • 위 코드처럼 부모 클래스인 Animal 클래스의 포인터인 j 에 Dog 클래스의 객체를 가리킬 수 있는 이유는 C++ 의 다형성(polymorphism) 으로 인해 가능함
    • 다형성이란, 여러 클래스들을 하나의 인터페이스로 동작시키는 개념
    • 여러개의 서로 다른 객체가 동일한 기능을 다양한 방법으로 처리할 수 있음
  • 부모 클래스의 포인터나 참조를 사용하여 자식 클래스의 객체에 접근할 수 있도록 함
  • 이를 통해 프로그램에서 일반적인 인터페이스를 사용하며, 런타임에 실제로 실행될 객체의 타입을 결정할 수 있음

바인딩(Binding)

  • 업캐스팅 상황에서 부모 클래스의 함수를 자식 클래스에서 오버로딩 시, ‘virtual’ 키워드로 선언하지 않으면, 자식 클래스에서 해당 함수 호출 시 부모클래스의 함수가 우선됨
    • 업캐스팅 상황이 아니면, 가상함수로 선언하지 않아도 오버라이딩 할 수 있음
  • 이유는 바인딩과 관련이 있음
  • 바인딩이란, 프로그램에서 식별자와 그에 대응하는 값을 연결하는 과정. 즉, 바인딩은 변수나 함수와 같은 식별자를 해당하는 메모리 위치나 코드 블록에 연결하는 것을 말함
  • 바인딩에는 정적 바인딩과 동적 바인딩이 있음
    • 정적 바인딩(Static Binding)
      • 컴파일 시간에 변수나 함수 호출대상이 결정되는 방식
      • 컴파일러는 식별자의 타입 정보를 바탕으로 해당하는 메모리 위치를 결정하거나, 함수 호출 대상을 정적으로 결정함
      • 컴파일러가 프로그램을 컴파일하는 과정에서 식별자와 값을 연결하므로, 실행시 바인딩이 발생하지 않음
    • 동적 바인딩(Dynamic Binding)
      • 런타임에 변수나 함수 호출 대상이 결정되는 방식
      • C++에서는 주로 가상함수를 사용하여 동적 바인딩을 구현
      • 객체의 타입에 따라 메모리 위치나 함수 호출대상이 동적으로 결정되므로, 실행 시 바인딩이 발생
  • 가상함수로 선언하지 않을 경우 정적 바인딩이 발생되기 때문에, 컴파일 타임에 함수 호출 대상이 결정되어 부모 클래스의 함수가 호출됨

추상화(Abstract)

  • 객체의 공통적인 특징과 기능을 하나의 추상 클래스로 표현하는 것
  • 실제로 구현되지 않은 순수한 가상 함수들을 가지고 있는 추상 클래스를 의미
  • 추상 클래스는 인스턴스를 생성할 수 없으며, 그 자체로 완전한 클래스가 아님
  • 추상 클래스는 단지 인터페이스 역할이며, 이를 상속받은 파생 클래스에서 정의된 순수 가상 함수들을 반드시 구현하여야 함.
  • 이를 통해 다형성을 구현하는 기반을 마련하고, 다른 클래스들 간의 공통된 인터페이스를 정의하여 객체 지향 프로그래밍의 유연성과 재사용성을 증가
  • 추상 클래스를 정의하기 위해서는 하나 이상의 순수 가상 함수를 포함해야 함
    • 순수 가상 함수(pure virtual function)는 ‘virtual’ 키워드와 함께 선언되며, 함수 바디가 없고 ‘= 0’ 으로 정의됨
    • 이를 통해 파생 클래스에서 해당 함수들을 오버라이딩하여 실제 기능 구현
    class AbstractClass {
    public:
    	virtual void example() = 0;
    }
    

인터페이스(Interface)

//인터페이스 선언
class Interface {
public:
	virtual void example1() = 0;
	virtual void example2() = 0;
}

//인터페이스를 상속하는 클래스 정의
class MyClass : public Interface
{
public:
	void example1()
	{
		//함수구현
	}
	void example()
	{
		/
  • 순수 가상 함수로만 구성된 클래스로, 실제로 구현을 갖지 않는 추상화된 형태의 클래스
  • 다형성을 활용하여 서로 다른 클래스들을 통일된 인터페이스를 사용하게 하여 코드의 재사용성과 유지 보수성을 향상
  • 인터페이스는 클래스의 외부와의 통신을 위한 계약으로 볼 수 있고, 특정 기능을 수행하는 메서드의 시그니처(함수 원형)만을 제공

클래스 포워드 선언(Forward Declaration)

  • 포워드 선언이란, 클래스의 선언을 미루어서 순환참조를 피하는 방법
    • 순환참조는 A.hpp 파일과 B.hpp 파일에서 서로를 include 하는 상황에서 발생하는 에러
    //A.hpp
    
    #include "B.hpp"
    
    class A
    {
    	//클래스 내용
    }
    
    //B.hpp
    
    #include "A.hpp"
    
    class B
    {
    	//클래스 내용
    }
    
    • 컴파일러가 클래스를 정확히 인식하지 못하여 에러가 발생함
  • 클래스의 멤버 변수나 멤버 함수를 선언하지 않고, 클래스의 이름만을 미리 선언하는 방법
  • 해당 클래스를 사용하는 코드에서는 클래스의 세부 구현을 알 필요 없이 클래스의 포인터나 참조를 사용할 수 있음
  • 클래스의 멤버 변수나 멤버 함수와 같은 세부 내용이 필요한 경우에는 헤더 파일의 하단에 해당 클래스의 헤더 파일을 포함시켜주어야 함
//A.hpp

class B;

class A
{
	//클래스 내용
}

#include "B.hpp"
//B.hpp

class A;

class B
{
	//클래스 내용
}

#include "A.hpp"

 

 

제가 공부한 내용을 기록하고 있습니다.

혹시 수정이 필요한 부분이 있다면, 댓글로 지적 부탁드립니다!

선한 관심과 도움 감사드립니다😊

반응형

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

[C++] 42SEOUL CPP03 개념 공부하기  (0) 2023.07.28
[C++] 42SEOUL CPP02 개념 공부하기  (0) 2023.07.28
[C++] 42SEOUL CPP01 개념, 함수 공부하기  (0) 2023.07.28