따라하자 씹어먹는 C++
상속받을 때 사용됐던 아래 문법을 보고 해석해봅시다
class Manager : public Employee
위와 같은 관계가 'is a' 관계이다.
근데 상속에 상속을 하다보면 기능들이 자꾸 하나 둘씩 늘어갈거다.
그렇게 점점 구체화
가 이루어진다.
그렇다 보면 'is a' 관계가 아니라 'has a' 관계가 될 수도 있다.
class Car {
private:
Engine e;
Brake b; // 아마 break 아니냐고 생각하는 사람들이 있을 텐데 :)
....
};
그럼 예전 예제에서 main문을 고쳐서 포인터로 클래스를 받아와 보자
int main() {
Base p;
Derived c;
std::cout << "===포인터 버전===" << std::endl;
Base* p_c = &c;
p_c->what();
return 0;
}
Derived is a Base
업캐스팅
이라고 한다.그럼 다운캐스팅은 가능할까?
Derived is a Base
만 기억하자.파생 is a 기반
. C++에서는 이 규칙 하나만 정해뒀다.다운캐스팅은 금지되었다.
Derived is a Base
을 기억하자.
Derived is a Base
를 깨려고 하는 친구들을 위해
사전방지용으로 dynamic_cast
를 지원한다.
Derived* p_c = dyanmic_cast<Derived*>(p_p);
virtual 키워드를 사용해서 코드를 짜보자
#include <iostream>
class Base {
public:
Base() { std::cout << "기반 클래스" << std::endl; }
virtual void what() { std::cout << "기반 클래스의 what()" << std::endl; }
};
class Derived : public Base {
public:
Derived() : Base() { std::cout << "파생 클래스" << std::endl; }
void what() { std::cout << "파생 클래스의 what()" << std::endl; }
};
int main() {
Base p;
Derived c;
Base* p_c = &c;
Base* p_p = &p;
std::cout << " == 실제 객체는 Base == " << std::endl;
p_p->what();
std::cout << " == 실제 객체는 Derived == " << std::endl;
p_c->what();
return 0;
}
결과는 Derived is a Base
니까 둘다 기반클래스의 what()을 들고올것으로 예상한다
class Base {
public:
Base() { std::cout << "기반 클래스" << std::endl; }
virtual void what() { std::cout << "기반 클래스의 what()" << std::endl; }
};
virtual function으로 오버라이딩 하려면 두함수의 꼴이 정확히 같아야함.
을 기억합시다. 아무때나 사용하는 게 아닙니다.C++11 (으악 나는 10인데)이상부터는 override 키워드를 넣을 수 있다.
소멸자는 virtual로 처리해줘야한다.
오버헤드(overhead)
가 난다.추상클래스
: 순수 가상함수를 최소 한개 포함하고, 반드시 상속되어야하는 클래스
class Animal {
public:
Animal() {}
virtual ~Animal() {}
virtual void speak() = 0;
};
#include <iostream>
class A {
public:
int a;
A() { std::cout << "A 생성자 호출" << std::endl; }
};
class B {
public:
int b;
B() { std::cout << "B 생성자 호출" << std::endl; }
};
class C : public A, public B {
public:
int c;
C() : A(), B() { std::cout << "C 생성자 호출" << std::endl; }
};
int main() { C c; }
A 생성자 호출 B 생성자 호출 C 생성자 호출
이렇다class A {
public:
int a;
};
class B {
public:
int a;
};
class C : public B, public A {
public:
int c;
};
int main() {
C c;
c.a = 3;
}
virtual 상속을 받아서 해결하는 방법
사람을 예로 들자
C/C++ 확대 축소
class Human {
// ...
};
class HandsomeHuman : public Human {
// ...
};
class SmartHuman : public Human {
// ...
};
class Me : public HandsomeHuman, public SmartHuman {
// ...
};
Human 클래스가 기반클래스가 되고, HandsomeHuman, SmartHuman이 Human의 파생함수, 그리고 Me가 HandsomeHuman, SmartHuman의 다중상속으로 파생함수가 된다.
근데 이렇게 짜면 바로 중복문제에 부딛히게된다. 그럴때 어떻게 짜느냐
class Human {
public:
// ...
};
class HandsomeHuman : public virtual Human {
// ...
};
class SmartHuman : public virtual Human {
// ...
};
class Me : public HandsomeHuman, public SmartHuman {
// ...
};