[C++기초] 7. 객체지향 프로그래밍3

INDEX

  1. 상속
  2. 생성자 호출 순서, 소멸자 호출 순서
  3. 다형성
  4. 다형성 정적 바인딩
  5. 다형성 동적 바인딩
  6. 다형성 가상 소멸자
  7. 다중 상속
  8. 추상 클래스
  9. 인터페이스

상속

상속이란?

파생 클래스의 접근 제어자

생성자 호출 순서, 소멸자 호출 순서

생성자 호출 순서

소멸자 호출 순서

다형성

멤버함수의 메모리

함수 오버라이딩

다형성 정적 바인딩

정적바인딩 - 멤버변수

Cat* yourCat = new Cat(5, "Mocha");
youtCat.Speak(); //Cat클래스의 메서드 실행


Animal* yourCat = new Cat(5, "Mocha");
yourCat.Speak(); //Animal 클래스의 메서드 실행

다형성 동적 바인딩

다형성 동적 바인딩

Java는 모든 것이 기본적으로 가상함수

C++에서는 virtual 키워드를 생략하면 정말 개판이 날 수 있다!!

가상함수

다형성 가상 소멸자

가상 소멸자는 모든 클래스마다 넣어야 한다!!! (매우 중요!!)

소멸자 주의해야 할 점!

소멸자 주의점1

소멸자 주의점2

virtual 키워드 생략하면 안된다! (메모리 누수날 수 있음)

잘못된 예제

//Animal.h
class Animal
{
public:
	~Animal();
private:
	int mAge;
};

//Cat.h
class Cat : public Animal
{
public:
	virtual ~Cat();
private:
	char* mName;
};

//Cat.cpp
Cat::~Cat()
{
	delete mName;
}

제대로 된 예제

//Animal.h
class Animal
{
public:
	virtual ~Animal();
private:
	int mAge;
};

//Cat.h
class Cat : public Animal
{
public:
	virtual ~Cat();
private:
	char* mName;
};

//Cat.cpp
Cat::~Cat()
{
	delete mName;
}

c++14/17에는 소멸자 가상함수 외에 다른 해결책이 있다.

다중 상속

예시

class TA : public Student, public Faculty
{
};

TA* myTa = new TA();

위의 코드의 경우 어느 부모의 생성자가 먼저 호출될까?

  • 파생 클래스에서 등장한 부모 클래스 순서대로

    • class TA : public Student, public Faculty -> Studet(), Faculty() 순으로 호출
    • class TA :public Faculty, public Student -> Faculty(), Student() 순으로 호출
  • 생성자의 순서를 지정할 수도 있다.

    class TA : public Studetn, public Faculty
    : Faculty()
    , Student()
    {
    };
    

    Faculty(), Student()순으로 호출

Java에서처럼 super()를 쓸 수 없는 이유

다중 상속이 가능하기 때문

부모가 같은 이름의 메서드를 가질 경우 어떻게 호출하나?

어떤 함수가 호출될 지 모호할 때는 우리가 직접 부모 클래스를 특정해줘야함.

myTA->Studetn::DisplayData();

다이아몬드 문제

다이아몬드문제

  • Q : Liger안에는 몇 개의 Animal이 있나?

    • A : 2개
  • Q : 그럼 그 문제는 어떻게 해결하나?

    • A : 가상 베이스 클래스를 사용한다
  • 다이아몬드문제2

  • But 근본적인 해결책이라고 하기엔 모호하다!
  • 이런걸 미리 신경써야 하는게 이상하다
    • 먼 훗날에 혼종이 나올거라는 걸 미리 알기 힘들다
  • So 다중상속을 최대한 쓰지 맙시다.
    • 대신 인터페이스를 쓰면 됩니다.

추상 클래스

추상클래스

예시

Animal.h

//Animal.h
class Animal
{
public:
	virtual ~Animal();
	
	//함수는 있지만 구현체는 없다는 의미
	virtual void Speak() = 0;
private:
	int mAge;
};

Cat.h

//Cat.h
class Cat : public Animal
{
public:
	~Cat();
	void Speak();
private:
	char* mName;
};

main.cpp

Animal myAnimal; //불가능

Animal* myAnimal = new Animal(); //불가능

Animal* myCat = new Cat(); //OK

Animal& myCatRef = *myCat; //OK

순수 가상함수

example

//Animal.h
class Animal
{
public:
        virtual void Speak() = 0;
private:
        int mAge;
};

//Cat.h
class Cat : public Animal
{
public:
        Cat(int age, const char* name);
void Speak();
private:
        char* mName;
};
//컴파일 에러
//Speak()이 구현 안 되어 있음

순수 가삼함수를 선언하는 법

virtual <return-type> <function-name> (<argument-list>) = 0;

virtual void Speak() = 0;

virtual float GetArea() = 0;

인터페이스