cpp module 03

이호용·2021년 8월 25일
0

cpp

목록 보기
4/16

항상 만들어야하는 항목!

디폴트 생성자(Default constructor)
복사 생성자(Copy constructor)
할당 연산자 오버로딩(Copy assignment operator)
소멸자(Destructor)

Inheritance 상속

지난시간에 공부했던 개념이다.

public 외부함수접근 o, 자식함수접근 o
protect 외부함수접근 x, 자식함수접근 o
private 외부함수접근 x, 자식함수접근 x

상속할때

class parents{
pubilic:

protect:

private

};

class child : public parent{
}

이런식으로 상속이 가능하다.

case 1

class child : public parent라고 하면 parent에 있는 데이터들을 public으로 받는다는것,

부모 클래스의 값들이 상속되면,
public -> public
protect -> protect
private -> privaet

case 2

class child : protect parent 라고 하면 parent에 있는 데이터를 protect 로 상속받는다.

부모 클래스의 값들이 상속되면
public -> protect
protect -> protect
private -> private

상속이 필요한 이유.

A라는 클래스와 B라는 클래스가 공통적으로 가지는 멤버 함수가있다.

상속을 사용하지 않으면 A라는 클래스와 B라는 클래스에 동일한 멤버함수를 생성해야하지만, C라는 클래스에 공통으로 사용되는 멤버 함수나 변수를 넣어주고 상속해주면 더 간단하게 관리하고 생성할 수 있다.

오버라이딩

함수 오버라이딩(overriding)이란 이미 정의된 함수를 무시하고, 같은 이름의 함수를 새롭게 정의하는 것이라고 할 수 있습니다.

override : 우선한다.

class parant {
public: 
	int a = 10;
}

class child : public parant {
public:
	int a = 20;
}

자식 클래스에도 a라는 변수가 있는데, 부모에 있는 a도 상속을 받음.

int main() {
	parant a;
    child b;
    
    std::cout << b.a; // 20;
    std::cout << b.parant::a // 10
}

정적바인딩

cpp는 정적바인딩이다!!!!!!!!! 매우 충격적
지금부터 보게 될 내용은 매우 충격적이 내용이다. 특히 c언어를 공부했던 사람이라면 정말 소름이 돋아서 잠이 안올수도 있다..

class parant {
public: 
	void print() {
    	std::cout << "From parant!!!" << std::endl; 
    }
}

class child : public parant {
public:
	void print() {
    	std::cout << "From child!!!" << std::endl;
    }
}

int main () {
	parant *A = new child();
    A->print(); // 이러면 무슨 값이 출력될까?
}
  1. parant *A = new child(); // 당근 컴파일 에러가 나겠지? 아니 작동함!!!!

    c++에서는 부모 클래스에 자식 클래스 주소를 넣을수 있음.

  2. *A에는 자식클래스 주소가 들어있음
  3. *A->print(); 이러면 "From parant!!!" 출력됨.
  4. A에 어떤 주소가 들어있든, A의 자료형에 해당하는 멤버함수를 불러옴.
  5. 이게 정적바인딩임! 이해 안된다고?, 응 그게 맞아.
    두들낙서

동적바인딩

너무 걱정하지마라 원래 대로 하는방법이 있으니..

class parant {
public: 
	virtual void print() {
    	std::cout << "From parant!!!" << std::endl; 
    }
}

class child : public parant {
public:
	void print() {
    	std::cout << "From child!!!" << std::endl;
    }
}

int main () {
	parant *A = new child();
    A->print(); // 이러면 무슨 값이 출력될까?
}

이러면 우리가 원래 예상했던 "Fome child!!!"가 출력된다.
parant의 print를 가상함수(쓸지 안쓸지 모르는 상태)로 만들고 돌리면 컴파일이 실행하는 시점에서 A 주소값을 확인하고 해당 주소값의 함수를 불러옴!

다중상속

다중상속은 인터페이스로부터만 받는다. 이러면 문제가 안생김.

인터페이스 : 모든 메서드가 순수 가상함수 이고, (비정적) 멤버 변수는 없는 클래스
추상 클래스 : 순수 가상함수가 하나이상 들어있는 클래스
다형적 클래스 : 가상함수가 하나이상 들어있는 클래스

정적바인딩 추가 설명

  6     std::cout << "==================[Constructor test]===============    ==" << std::endl;
  7     ScavTrap A;
  8     ClapTrap A_tmp;
  9     std::cout << std::endl;
 10     ScavTrap B("hoylee");
 11     std::cout << std::endl;
 12     ScavTrap C(B);
 13     std::cout << std::endl;
 14
 15
 16     std::cout << "==================[attack test]=================" <    < std::endl;
 17     A.attack("lopper");
 18     A_tmp.attack("lopper");
 19     std::cout << std::endl;

ScavTrap은 ClapTrap에서 attack 매게변수를 상속받았음. 하지만, ScavTrap은 클래스에도 attack 존재.
A가 attack을 호출했을때, ScavTrap::attack이 불러짐.

또한 ScavTrap 자료형으로 생성된 인스턴스들은, 소멸할때 자식클래스의 소멸자 부모클래스의 소멸자 순서대로 호출됨.

만약 부모클래스의 소멸자가 호출되기 싫으면 부모 소멸자를 가상 소멸자로 선언해 두면됨.

다이아몬드 트랩 상속

  5 class ClapTrap{
  6     private:
  5 class ScavTrap : virtual public ClapTrap {
  6 public:
  5 class FragTrap : virtual public ClapTrap {
  6 public:

가장 부모인, ClapTrap이 있고!
ClapTrap을 상속 받는 자식 클래스 ScavTrap, FragTrap이 있다.

그리고 ScavTrap, FragTrap를 상속 받는 DiamondTrap이 있는데

DiamondTrap이 상속받을때 ClapTrap을 한번만 상속 받을려면 위에서 처럼 상속해줄때 virtual형태로 상속해주면 된다.

이렇게 상속받은 DiamondTrap은 부모 클래스와 자신의 기능까지 모두 구현된다!

0개의 댓글