프로그래밍 언어/C++

10) 상속

busy맨 2023. 12. 9. 00:50

1. 상속 개념

1) C++에서의 상속(Inheritance)

  • 클래스 사이에서의 상속 관계 정의
    • 객체 사이에는 상속 관계 없음
  • 기존의 클래스가 가진 기능을 이어받아서 새로운 클래스를 정의하는 것
    • 기본 클래스: 상속을 해주는 클래스, 일반적인 특징을 제공
    • 파생 클래스: 상속을 받는 클래스, 일반적인 특징 + 구체적인 특징
      • 기본 클래스의 속성과 기능을 물려받고 자신만의 속성과 기능을 추가하여 작성
  • 기본 클래스에서 파생 클래스로 갈수록 클래스의 개념이 구체화
  • 다중 상속을 통한 클래스의 재활용성 높임
    • 다른 클래스를 상속 받아서 새로운 클래스를 정의할 때, 기존의 클래스에 구현되어 있는 기능은 새롭게 정의할
      필요 X

 

2) 상속의 목적 및 장점

  • 간결한 클래스 작성
    • 기본 클래스의 기능을 물려받아 파생 클래스를 간결하게 작성
  • 클래스 간의 계층적 분류 및 관리의 용이함
    • 상속은 클래스들의 구조적 관계 파악 용이
  • 클래스 재사용과 확장을 통한 소프트웨어 생산성 향상
    • 빠른 소프트웨어 생산 필요
    • 상속을 받아 새로운 기능 확장

 

2. 파생 클래스 정의 및 객체의 생성 방법

1) 상속 선언

  • 파생 클래스 정의
    • 클래스 이름 다음에 콜론을 적고 public 키워드와 함께 기본 클래스 이름을 적어줌

  • 파생 클래스의 멤버
    • 상속받는 멤버 변수는 다시 정의하지 않음
    • 새로 추가된 멤버 변수나 멤버 함수 정의
    • 상속 받은 멤버 함수 중에서 기본 클래스와 다르게 처리할 멤버 함수를 재정의(overriding)

 

Ex) Point 클래스를 상속받는 ColorPoint 클래스 만들기

#include <iostream>
#include <string>
using namespace std;
// 2차원 평면에서 한 점을 표현하는 클래스 Point 선언
class Point {
	int x, y; //한 점 (x,y) 좌표값
public:
	void set(int x, int y) { this->x = x; this->y = y; }
	void showPoint() {
		cout << "(" << x << "," << y << ")" << endl;
	}
};
class ColorPoint : public Point { // 2차원 평면에서 컬러점을 표현하는 클래스 ColorPoint.Point를 상속받음
		string color;// 점의 색 표현
public:
	void setColor(string color) { this->color = color; }
	void showColorPoint();
};
void ColorPoint::showColorPoint() {
	cout << color << ":";
	showPoint(); // Point의 showPoint() 호출
}
int main() {
	Point p; // 기본 클래스의 객체 생성
	ColorPoint cp; // 파생 클래스의 객체 생성
	cp.set(3, 4); // 기본 클래스의 멤버 호출
	cp.setColor("Red"); // 파생 클래스의 멤버 호출
	cp.showColorPoint(); // 파생 클래스의 멤버 호출
}

2) protected 접근 지정

  • 접근 지정자
    • private
      • 선언된 클래스 내에서만 접근 가능
      • 파생 클래스에서도 기본 클래스의 private 멤버 직접 접근 불가
    • public
      • 선언된 클래스나 외부 어떤 클래스, 모든 외부 함수에 접근 허용
      • 파생 클래스에서 기본 클래스의 public 멤버 접근 가능
    • protected
      • 선언된 클래스에서 접근 가능
      • 파생 클래스에만 접근 허용
        • 다른 클래스나 외부 함수에서는 protected 멤버를 접근 불가

Ex) protected 멤버에 대한 접근

#include <iostream>
#include <string>
using namespace std;
class Point {
protected:
	int x, y; //한 점 (x,y) 좌표값
public:
	void set(int x, int y);
	void showPoint();
};
void Point::set(int x, int y) {
	this->x = x;
	this->y = y;
}
void Point::showPoint() {
	cout << "(" << x << "," << y << ")" << endl;
}
class ColorPoint : public Point {
	string color;
public:
	void setColor(string color);
	void showColorPoint();
	bool equals(ColorPoint p);
};
void ColorPoint::setColor(string color) {
	this->color = color;
}

void ColorPoint::showColorPoint() {
	cout << color << ":";
	showPoint(); // Point 클래스의 showPoint() 호출
}
bool ColorPoint::equals(ColorPoint p) {
	if (x == p.x && y == p.y && color == p.color)
		return true;
	else
		return false;
}
int main() {
	Point p; // 기본 클래스의 객체 생성
	p.set(2, 3); 
	//p.x = 5; Error
	//p.y = 5; Error
	p.showPoint();
	ColorPoint cp; // 파생 클래스의 객체 생성
	//cp.x = 10; Error
	//cp.y = 10; Error
	cp.set(3, 4);
	cp.setColor("Red");
	cp.showColorPoint();
	ColorPoint cp2;
	cp2.set(3, 4);
	cp2.setColor("Red");
	cout << ((cp.equals(cp2)) ? "true" : "false"); 
}

 

3. 파생클래스의 생성자 및 소멸자

1) 상속 관계의 생성자와 소멸자 실행

  • 파생 클래스의 객체가 생성될 때 파생 클래스의 생성자와 기본 클래스의 생성자가 모두 실행
  • 기본 클래스의 생성자가 먼저 실행된 후 파생 클래스의 생성자가 실행
  • 파생 클래스의 객체가 소멸될 때, 파생 클래스의 소멸자가 먼저 실행되고 기본 클래스의 소멸자가 나중에 실행
    • 파생 클래스 소멸자는 내부적으로 기본 클래스의 소멸자를 호출

  • 기본 클래스의 디폴트 생성자의 암시적 호출

 

  • 기본 클래스에 디폴트 생성자가 없는 경우 → 에러 발생

 

  • 파생 클래스의 매개변수를 가진 생성자가 기본 클래스의 디폴트 생성자 호출

 

  • 파생 클래스의 생성자에서 명시적으로 기본 클래스의 특정한 생성자의 명시적 호출

 

4. 접근 변경자

1) 접근 변경자

  • 기본 클래스의 멤버의 접근 속성을 어떻게 계승하지 결정
  • private  멤버는 파생클래스에서 접근 불
  • public
    • 기본 클래스의 protected. public 멤버 속성을 그대로 계승
  • private
    • 기본 클래스의 protected, public 멤버를 private로 계승
  • protected
    • 기본 클래스의 protected, public 멤버를 proteced로 계승

 

5. 다중 상속

1) 다중 상속의 필요성

  • 두 개의 기본 클래스를 상속 받을 필요가 있는 경우
    • 모든 기본 클래스의 멤버를 상속 받음

 

2) 다중 상속의 문제점: 기본 클래스 멤버 접근의 모호성

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

 

3) 가상 상속

  • 다중 상속으로 인한 기본 클래스 멤버의 중복 상속 해결
  • 가상 상속
    • 파생 클래스의 선언문에서 기본 클래스 앞에 virtual 키워드로 선언
    • 파생 클래스의 객체가 생성될 때 이미 할당되어 있다면, 기본 클래스의 멤버 공간을 한 번만 할당
      • 기본 클래스의 멤버가 중복 생성되는 것을 방지

 

4) 충돌의 가능성

  • 2개의 부모 클래스에 같은 이름의 멤버가 있는 경우

'프로그래밍 언어 > C++' 카테고리의 다른 글

12) 템플릿  (1) 2023.12.09
11) 가상 함수와 추상 클래스  (0) 2023.12.09
9) friend와 연산자 중복  (0) 2023.12.08
8) 함수와 참조, 복사생성자  (0) 2023.12.08
7) 여러가지 객체의 생성 방법  (1) 2023.11.03