TIL 2024/8/21

Sung Joo Lee·2024년 8월 21일

이전 포스트.

이번 포스트는 이전의 상속의 개요부터 다시 시작합니다.

상속 part 2

기본 문법


class Base{

};

class Derived : access - specifier Base { // 왼쪽 :  Deirved class , 오른 쪽 : Base class 

};

access - specifier : public, private, protected 등과 같이 접근 권한을 의미

  • public 상속
    • 가장 흔히 사용되는 상속 방식
    • “is - a ” 관계의 정의와 가장 일치하는 상속 방식
  • Private과 protected 상속
    • “has - a ”와 유사한 관계를 정의하는 상속
    • 소유와는 차이가 존재
    • 솔직히 많이 사용하지 않음

예시 코드

#include <iostream>

class Entity {

protected: // 새롭게 배울 접근 제한자
	int x;
	int y;

public:
	Entity(int x , int y)
		: x{x},y{y}{}

	void showPosition()
	{
		std::cout << "[" << x << "," << y << "]" << std::endl;
	}

	void Talk()
	{
		std::cout << "Hello." << std::endl;
	}
};

class Player : public Entity {

private:
	int hp, xp, speed;

public:
	Player(int x , int y ,int speed)
		: hp{x},xp{y},speed{speed}{}

	void Move(int dx, int dy)
	{
		x += dx;
		y -= dy;
	}
};

int main()
{
	Entity e{ 1,1 };
	e.showPosition();
	e.Talk();

	Player p{1,1,1};
	p.Move(2, 2);
	
	///// Entitiy를 상속을 받았기 때문에 사용이 가능하다.
	p.showPosition();
	p.Talk();

	return 0;
}

protected 멤버


  • Base class에서 접근 가능

  • Derived Class에서 접근 가능

  • 기본 또는 유도 클래스의 “객체”로부터는 접근 불가능!

    • Private를 생각해 보자. 클래스에서는 접근 가능하고, 객체로부터는 접근이 불가능 하였음
    • Protected는 “상속이 이루어지는 private”라고 생각하면 편하다.
    • Private는 유도 클래스에서 접근이 불가능 → private는 상속과 관계없이 무조건 ( 자신 ) 클래스 내부에서만 접근 가능함

예시 코드

#include <iostream>

class Entity {

protected:
	int x;
	int y;

public:	
	Entity() = default;

	Entity(int x , int y)
		: x{x},y{y}{}

	void showPosition()
	{
		std::cout << "[" << x << "," << y << "]" << std::endl;
	}

	void Talk()
	{
		std::cout << "Hello." << std::endl;
	}
};

class Player : public Entity {

private:
	int hp, xp, speed;

public:

	Player(int x , int y ,int speed)
		: hp{x},xp{y},speed{speed}{}

	void Move(int dx, int dy)
	{
		//Entity의  x,y에 접근이 가능하다.
		x += dx;
		y -= dy;
	}

	void setHp(int hp)
	{
		this->hp = hp;
	}
};

int main()
{
	Entity e{ 1,1 };
	e.showPosition();
	e.Talk();

	Player p{1,1,1};
	p.Move(2, 2);
	
	///// Entitiy를 상속을 받았기 때문에 사용이 가능하다.
	p.Move(-1, -2);
	p.showPosition();
	p.Talk();
	
	return 0;
}

상속했을 때 메모리

class Base
{
public:
	int a;
protected:
	int b;
private:
	int c;
};

class Derived : public Base
{

};

int main()
{
	Derived d;
	d.a = 10; // a 만 public이기 때문에 객체 접근이 가능함

	std::cout << sizeof(int) << std::endl; // 4 byte
	std::cout << sizeof(Base) << std::endl; // 12 byte (int 변수가 4개)
	std::cout << sizeof(Derived) << std::endl; // 12 byte (int 변수가 4개)

}

d.b, d.c와 같이 직접 객체에 접근이 불가능 하지만 메모리에 올라가 있지 않은 것은 아니다!

상속에서의 생성자와 소멸자


상속에서의 생성자

  • 유도 클래스는 기본 클래스의 멤버를 포함하므로, 유도 클래스가 초기화 되기 이전에 기본 클래스에서 상속된 부분이 반드시 초기화 되어야 함

  • 유도 클래스 객체가 생성될 때

    • 먼저 기본 클래스의 생성자가 호출되고
    • 그 이후 유도 클래스의 생성자가 호출됨
class Base
{
public:
	Base() {
		std::cout << "Base 생성자 생성 " << std::endl;
	}

};

class Derived : public Base
{
public:
	Derived() {
		std::cout << "Derived 생성자 생성" << std::endl;
	}
};

int main()
{
	Derived d;
}

위의 코드를 실행 해보면 Base class의 생성자가 호출이 된다.

상속에서의 소멸자

  • 소멸자는 생성자와 반대 순서로 호출됨

  • 즉, 유도 클래스가 소멸될 때,

    • 먼저 유도 클래스의 소멸자가 호출되고,
    • 그 이후 기본 클래스의 소멸자가 호출됨

생성자와 소멸자의 상속

  • 유도 클래스는 기본 클래스의 생성자, 소멸자 및 오버로딩된 대입 연산자를 상속하지 않음

  • 대신 , 기본 클래스의 생성자, 소멸자 및 오버로딩된 대입 연산자를 유도 클래스로부터 호출이 가능함

    • 나중에 자세하게 설명해줌
profile
개발로그

0개의 댓글