C++ 상속

2024. 12. 23. 20:51·C++

오늘 배운 내용 중 중요한 부분인 상속을 좀 더 자세히 이해해 보고자, 구글링과 유튜브 영상을 통해 공부한 후 정리한 글이다.

1. 상속을 사용하는 이유

  • 클래스 간의 관계 설정하여 코드 재사용성 높이기
  • Class Interface Consistency : 일관적인 클래스 인터페이스 구성 가능
    • abstract / interface
    • pure virtual function
  • Dynamic Function Binding : 동적 바인딩을 사용하기 (C++는 기본적으로 정적 바인딩)
    • virtual function
    • virtual table

2. 상속 기본 예제 및 접근 지정자

아주 간단한 상속 예제

  • 상속 받은 클래스는 부모의 함수를 사용할 수 있다.(public 이니까)
#include <iostream>

using namespace std;

class Animal
{
public:
	void sleep() const
	{
		cout << "I'm sleeping\n";
	}
};

class Human : public Animal
{
public:
	void driveCar() const
	{
		cout << "I'm driving\n";
	}
};

int main()
{
	Human me;
	me.driveCar(); // I'm driving
	me.sleep(); // I'm sleeping

	return 0;
}

 

 

접근 권한 키워드 예제

  • 우리가 Base클래스를 상속할 때 어떤 접근 권한 키워드로 가져올 것인가에 따라 클래스의 동작이 달라지게 된다.
  • 정리하기에 앞서...
    • 앞으로 이야기 할 내용들은 상속한 자식 클래스로 만들어진 인스턴스 입장에서 생각해야 한다. 아래 코드 예시로 들면, main 함수에서 사용할 때를 말하는 것이다.
    • 상속받은 클래스 내에서의 동작은 모두 같다. (public과 protected 까지 접근 가능하다)
    • 지금 예제는 한번의 상속만 있기에 크게 와닿지 않지만, 다중 상속을 하는 경우 차이점을 느낄 수 있다.
  • Base 클래스
    • 클래스 내부에서는 당연하게 모두 접근이 가능하다.
      • 그렇기 때문에 setter함수를 public 함수로 만들어서 상속받은 클래스나 인스턴스에서 사용하도록 만든다.
    • main함수에 생성된 인스턴스 입장에서는 public함수만 사용이 가능하다.
  • public으로 상속
    • 부모 클래스에 선언된 그대로 받아들이면 된다.
      • 클래스 내부에서는 public과 protected에 접근이 가능할 것이고,
      • main 함수에 클래스로 생성된 인스턴스 입장에서는 public만 접근이 가능할 것이다.
  • protected로 상속
    • public 이 protected로 바뀌게 된다.
    • 클래스 내부에서의 동작은 같지만, main 함수에서 생성한 인스턴스는(derived2) public 함수인 setter 함수를 사용하지 못하게 된다.
  • private로 상속
    • public과 protected 모두 private로 바뀌게 된다.
    • 현재 예시에서는 protected와  똑같이 동작한다.
  • 아래의 예시 중 주석 표시가 된 코드는 오류를 발생시키는(엑세스 할 수 없음) 코드이다.
#include <iostream>
using namespace std;

class Base
{
private:
	int pri;
protected:
	int pro;

public:
	void SetPri(int n)
	{
		pri = n;
	}
	void SetPro(int n)
	{
		pro = n;
	}
};

class Derived1 : public Base
{
public:
	void Test()
	{
		Base::pro = 100;
		//Base::pri = 100; 
	}
};

//이 경우 public 이 protected로 보인다
class Derived2 : protected Base
{
	void Test()
	{
		Base::pro = 100;		
		//Base::pri = 100; 
	}
};

//이 경우 public과 protected가 모두 private로 보인다.
class Derived3 : private Base
{
	void Test()
	{
		Base::pro = 100;
		//Base::pri = 100; 
	}
};
int main()
{
	Base base;
	base.SetPri(10);
	base.SetPro(100);
	//base.pro = 0;
	//base.pri = 0;


	Derived1 derived1;
	derived1.SetPri(100);
	derived1.SetPro(100);

	Derived2 derived2;	
	//derived2.SetPri(100);
	//derived2.SetPro(100);

	Derived3 derived3;
	//derived3.SetPri(100);
	//derived3.SetPro(100);
}

3. 생성자 소멸자 및 가상 함수

1. 생성자 소멸자 호출 순서

  • 기본적인 예제 (항상 부모의 생성자 먼저, 자식의 소멸자 먼저)
#include <iostream>
using namespace std;

class Animal
{
public:
	Animal()
	{
		cout << "animal constructor\n";
	}

	~Animal()
	{
		cout << "animal destructor\n";
	}
};

class Cat : public Animal
{
public:
	Cat()
	{
		cout << "cat constructor\n";
	}
	~Cat()
	{
		cout << "cat destructor\n";
	}
};

int main()
{
	Cat cat; //1
    
    	//Animal* animalptr = new Animal(); //2
	//delete animalptr;

	//Cat* catptr = new Cat(); //3
	//delete catptr;
}

순서대로 1, 2, 3 각각을 실행했을 때의 결과

  • 주의할 사항
    • 아래 코드를 실행시키면, cat 의 소멸자가 호출되지 않는 문제점이 존재한다.
    • 그렇기 때문에 해결책으로
      • base class의 소멸자를 virtual public으로 선언하기 (대부분의 경우)
      • base class의 소멸자를 protected로 선언하기 (base class를 오브젝트로 만들지 않는 경우)
Animal* polyCat = new Cat();

 

2. virtual 을 이용한 Dynamic Polymorphism

  • virtual function 만들기
    • 부모 클래스에서 virtual 함수를 만든다면, 앞에 virtual 을 붙여주고,
    • 해당 virtual 함수를 상속받았다면, override 키워드를 뒤에 붙여주도록 한다.
  • 간단한 dynamic polymorphism 예제
    • 아래와 같은 코드를 작성하면, 컴파일 타임이 아니라 런타임에 우리가 polyAnimal의 타입을 정해줄 수 있다.
    • 1을 입력한 경우 meow를 2를 입력한 경우 animal이 출력될 것이다.
#include <iostream>
using namespace std;

class Animal
{
public:
	virtual void speak()
	{
		cout << "animal\n";
	}
	virtual ~Animal() = default;
};

class Cat : public Animal
{
public:
	void speak() override
	{
		cout << "meow\n";
	}
};

int main()
{
	int i = 0;
	cin >> i;

	Animal* polyAnimal;

	if (i == 1)
		polyAnimal = new Cat();
	else
		polyAnimal = new Animal();

	polyAnimal->speak();
	delete polyAnimal;
}

4. Virtual Table

  • 가상함수가 아닌 일반 함수로 선언된 경우
  • Animal 클래스는 double변수 한개이므로 크기가 8 byte
  • Cat 클래스는 Animal 클래스의 크기 + 자기가 가진 double 변수 8byte = 16byte
#include <iostream>
using namespace std;

class Animal
{
public:
	void speak()
	{
		cout << "animal\n";
	}
	//virtual ~Animal() = default;

private:
	double height;
};

class Cat : public Animal
{
public:
	void speak()
	{
		cout << "meow\n";
	}
private:
	double weight;
};


int main()
{
	cout << "Animal size: " << sizeof(Animal) << "\n"; //8(height - double) byte
	cout << "Cat size: " << sizeof(Cat) << "\n"; //8(height) + 8(weight) byte		
}
  • speak 함수는 virtual로 선언한 경우
    • 아래 그림 처럼 virtual table이 생성되기 때문에 64bit 컴퓨터에서 포인터 변수 한개의 크기(8byte)가 추가된다.
    • 가상함수 테이블은 클래스마다 하나씩 가지고 있다 (개체마다 아님!)
#include <iostream>
using namespace std;

class Animal
{
public:
	virtual void speak()
	{
		cout << "animal\n";
	}
	//virtual ~Animal() = default;

private:
	double height;
};

class Cat : public Animal
{
public:
	void speak() override
	{
		cout << "meow\n";
	}
private:
	double weight;
};


int main()
{
	cout << "Animal size: " << sizeof(Animal) << "\n"; //16 byte
	cout << "Cat size: " << sizeof(Cat) << "\n"; //24 byte		
}

 

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

C++ TIL day 9  (3) 2024.12.27
C++ TIL day 8  (0) 2024.12.26
Smart Pointer 보충  (0) 2024.12.24
C++ TIL day 7  (2) 2024.12.24
C++ TIL day 6  (0) 2024.12.23
'C++' 카테고리의 다른 글
  • C++ TIL day 8
  • Smart Pointer 보충
  • C++ TIL day 7
  • C++ TIL day 6
gbleem
gbleem
gbleem 님의 블로그 입니다.
  • gbleem
    gbleem 님의 블로그
    gbleem
  • 전체
    오늘
    어제
    • 분류 전체보기 (184)
      • Unreal Engine (73)
      • C++ (19)
      • 알고리즘(코딩테스트) (27)
      • TIL (60)
      • CS (4)
      • 툴 (1)
  • 블로그 메뉴

    • 홈
    • 카테고리
  • 링크

    • 과제용 깃허브
    • 깃허브
    • velog
  • 공지사항

  • 인기 글

  • 태그

    applydamage
    싱글턴
    gamestate
    actor 클래스
    DP
    템플릿
    map을 vector로 복사
    enhanced input system
    addonscreendebugmessage
    character animation
    C++
    motion matching
    매크로 지정자
    cin함수
    blend pose
    BFS
    Vector
    additive animation
    상속
    const
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
gbleem
C++ 상속
상단으로

티스토리툴바