본문 바로가기
C++/기초(두들낙서)

[C++] 상속

by Meaning_ 2022. 11. 15.
728x90
반응형

기본 클래스의 속성과 기능을 파생 클래스에 물려주는 것 

기본 클래스의 속성과 기능을 물려받고 자신 만의 속성과 기능 추가하여 작성 

 

업캐스팅

 

파생 클래스 포인터가 기본 클래스 포인터에 치환

Point의 자식 클래스가 ColorPoint

 

ColorPoint cp;
ColorPoint *pDer=&cp;
Point* pBase=pDer; //업캐스팅

 

다운 캐스팅

 기본 클래스의 포인터가 파생클래스의 포인터에 치환되는 것

 

ColorPoint cp;
ColorPoint *pDer;
Point* pBase=&cp;//업캐스팅 -> 부모타입 변수에 자식타입 변수 대입
pDer=(ColorPont*)pBase;//다운캐스팅 -> 자식 타입 변수에 부모타입 변수 대입

 

 

상속 관계의 생성자와 소멸자

 

Q1. 파생 클래스의 객체가 생성될 때 파생 클래스의 생성자와 기본 클래스의 생성자가 모두 실행되는가? 아니면 파생클래스의 생성자만 실행되는가?

 

=> 둘 다 실행된다.

 

Q2. 파생 클래스의 생성자와 기본 클래스의 생성자 중 어떤 생성자가 먼저 실행되는가?

=> 기본 클래스의 생성자가 먼저 실행된 후 파생클래스의 생성자가 실행된다. (부모가 먼저 실행)

소멸자는 자식이 먼저 실행

 

🎀 몇가지 규칙들

1. 컴파일러에 의해 묵시적으로 기본 클래스의 생성자 선택하는 경우,  컴파일러는 묵시적으로 기본 클래스의 기본 생성자 호출하도록 컴파일함. 

2. 매개변수를 가진 파생클래스의 생성자는 묵시적으로 기본 클래스의 생성자 선택.

3. 파생 클래스의 생성자에서 명시적으로 기본 클래스의 생성자 선택. 

 

 

생성자 매개변수 전달

 

class TV{
	int size;
public:
	TV(int size){this->size=size};
 }
 
 class WideTV: public TV{
 	bool videoln;
 public:
 	WideTV(int size,bool videoln):TV(size){
    	this->videoln=videoln
    }
 
 }
 
 class SmartTV: public WideTV{
 	string ipAddr;
  public:
  	SmartTv(string ipAddr,int size):WideTv(size,true){
    	this->ipAddr=ipAddr;
     }
     
  }
 	
 }

 

private 상속 사례

 

class Derived : private Base

인 경우 Base클래스가 private으로 상속이 됨

 

class Base{

	int a;
 protected:
 	void setA(int a){this->a=a;}
 public:
	void show(){cout<<a;}
}

class Derived : private Base{

	int b;
 protected:
 	void setB(int b){this->b=b;}
 public :
 	void showB(){cout<<b;}
    
 }

 

protected는 외부에서 접근할 수 없음

 

Derived x;

x.a=5 //안됨 -> a는 private

x.setA(10); //안됨 -> setA는 protected

x.showA(); //안됨 -> 왜냐면 Base가 private로 바뀌었으니까! (Derived에서 Base에서 접근하는거니까)

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
#include <string>
#include<cmath>
 
using namespace std;
 
class Base {
 
    int a;
 
protected:
    void setA(int a) {
        this->= a;
 
    }
 
    void showA() {
        cout << a << endl;
    }
 
};
 
class Derived :private Base {
 
    int b;
 
protected:
    void setB(int b) {
        this->- b;
    }
 
public:
    void showB() {
        setA(5);
        showA();
        cout << b << endl;
    }
};
 
class GrandDerived :private Derived {
    int c;
protected:
    void setAB(int x) {
        setA(x);
        showA();
        setB(x);// Derived가 private으로 받아와지면 setB()도 private이여야 하는거 아닌지.. 근데 어떻게 접근이 가능한건지...
        showB();
    }
};
cs

 

여기서 setA()와 showA()가 빨간줄이 뜨는데

그 이유는 setA()와 showA()가 Base 클래스에 있는 함수인데 GrandDerived에서 Derived->Base 까지 총 두계단을 올라가서 접근하기 때문에 안되는것이라 한다!

 

다중 상속의 문제점

 

기본 클래스 멤버의 중복상속

 

예를 들어 

class BaseIO{

public:
	int mode;
 }
 
class In: public BaseIO{

public:
	int readPos;
    
}


class Out:public BaseIO{

public:
	int writePos;
 }
 
 
 class InOut:public In,public Out{
 
 public:
 
	bool safe;
    
  }
  
  int main(){
  
  	InOut inObj;
    
    inObj.mode; //mode가 모호
    
    }

mode가 In,Out에 둘다 생성되므로 어떤 클래스의 mode인지 모호해진다. 

 

virtual

 

다중상속으로 인한 기본 클래스멤버의 중복상속을 해결하는 방법은 가상 상속이 있다!

파생 클래스 선언문에서 기본 클래스 앞에 virtual로 선언

파생 클래스의 객체가 생성될 때 기본 클래스의 멤버는 오직 한번만 실행 

-> 기본 클래스의 멤버가 중복하여 생성되는 것 방지 

 

class In:virtual public BaseIO{

}

class Out: virtual public BaseIO{

}

 

아까 모호했던 mode가 하나에만 생성된다. 

728x90
반응형

댓글