C++

12. 상속 (inheritance)

2024. 11. 19. 11:04
목차
  1. - 객체지향언어의의 특징 3가지
  2. 1. 상속(inheritance)
  3. 1) public 상속 접근제어
  4. 2) private 상속 접근제어
  5. ▶ In-class member initializer
  6. 3) protected  상속 제어접근
  7. 4) 계층적 다중 상속
  8. 5) 여러 개 의 기본 클래스를 동시에 상속
728x90
#include <iostream>
using std::cout;
class A {  // 기본 클래스, 부모 클래스 
private:
	void a1() { cout << "a1\n"; }
	void a2() { cout << "a2\n"; }
public:
	void b1() { cout << "b1\n"; }
	void b2() { cout << "b2\n"; }
	void b3() { cout << "b3\n"; }
	void b4() { cout << "b4\n"; }
};

class B { }; //class B : public A { }; //파생클래스, 자식클래스

int main() {
	A aa;
	aa.b1();  // b1 출력
	B bb;
	bb.  //아무것도 뜨지않음
	return 0;
}

↓ 상속 추가

#include <iostream>
using std::cout;
class A {  // 기본 클래스, 부모 클래스 
private:
	void a1() { cout << "a1\n"; }
	void a2() { cout << "a2\n"; }
public:
	void b1() { cout << "b1\n"; }
	void b2() { cout << "b2\n"; }
	void b3() { cout << "b3\n"; }
	void b4() { cout << "b4\n"; }
};

class B : public A {  //상속

}; //class B : public A { }; //파생클래스, 자식클래스

int main() {
	A aa;
	aa.b1();  // b1 출력
	B bb;
	bb.  // A의 public클래스에 있는 것들이 뜸
	return 0;
}

 

- 상속을 하게되면 부모의 public울 받아와 사용할 수 있다.

 

#include <iostream> // 표준 입출력 라이브러리 포함
using std::cout; // cout을 std 네임스페이스에서 사용

// 클래스 A 정의 - 기본 클래스(부모 클래스)
class A {  
private:
	// private 멤버 함수 - 클래스 외부에서 접근 불가
	void a1() { cout << "a1\n"; } // a1 함수 정의
	void a2() { cout << "a2\n"; } // a2 함수 정의

public:
	// public 멤버 함수 - 클래스 외부에서 접근 가능
	void b1() { cout << "b1\n"; } // b1 함수 정의
	void b2() { cout << "b2\n"; } // b2 함수 정의
	void b3() { cout << "b3\n"; } // b3 함수 정의
	void b4() { cout << "b4\n"; } // b4 함수 정의
};

// 클래스 B 정의 - 클래스 A를 상속받는 파생 클래스(자식 클래스)
class B : public A {  
// B 클래스는 A 클래스의 모든 public 및 protected 멤버에 접근 가능
}; // class B : public A { }; 

int main() {
	A aa; // 클래스 A의 객체 aa 생성
	aa.b1();  // aa 객체를 통해 b1 호출, "b1" 출력

	B bb; // 클래스 B의 객체 bb 생성
	bb.b1(); // b1은 A 클래스의 public 멤버이므로 접근 가능하지만, B 클래스의 bb 객체로는 접근 불가
	// 이 부분에서 b1 호출 시 컴파일 오류 발생
	return 0; // 프로그램 종료
}

 

- 객체지향언어의의 특징 3가지

  1. 캡슐화
  2. 다형성
  3. 상속성

 

1. 상속(inheritance)

 

 다양한 언어로 보는 간단한 예제

 

- python

class Animal:
    def sound(self):
        print("Animal sound")

class Dog(Animal):
    def sound(self):
        print("Bark")

dog = Dog()
dog.sound()  # "Bark" 출력

 

- java

class Animal {
    void sound() {
        System.out.println("Animal sound");
    }
}

class Dog extends Animal {
    void sound() {
        System.out.println("Bark");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.sound(); // "Bark" 출력
    }
}

 

- javascript 

class Animal {
    sound() {
        console.log("Animal sound");
    }
}

class Dog extends Animal {
    sound() {
        console.log("Bark");
    }
}

const dog = new Dog();
dog.sound(); // "Bark" 출력

 

 

▶ 상속 과정

  - 계층적으로 상속을 받게 되면 기존의 클래스를 그대로 사용할 수 있는 장점이 있고 또한 새로운 클래스를 보다 쉽게 만들 수 있다.

 

▶ 기본클래스와 파생클래스 : is-a, is_a, is a 관계 

is a = 상속

 

▶클래스 상속 형식

 

1) public 상속 접근제어

▶ 상속 접근제어 속성에 따른 파생 클래스 멤버의 속성변화

  1. 상속 접근 제어:
    • 표의 맨 위에는 class Dog : public Animal이라는 문구가 있다. 이는 Dog 클래스가 Animal 클래스를 public으로 상속받고 있음을 나타낸다.
  2.  기본 클래스의 속성:
    • 표의 첫 번째 열은 기본 클래스 Animal의 멤버 접근 제어를 나타낸다. 각 행은 private, protected, public의 세 가지 접근 수준을 보여준다.
  3.  접근 제어 규칙:
    • 각 셀은 Dog 클래스에서 접근할 수 있는지를 나타낸다.
           예를 들어
      • private: 기본 클래스에서 private로 선언된 멤버는 파생 클래스에서 접근할 수 없다. (모든 경우에서 "접근 불가")
      • protected: 기본 클래스에서 protected로 선언된 멤버는 public 상속을 통해 파생 클래스에서 protected로 접근할 수 있다. (즉, Dog 클래스에서 접근 가능하지만 외부에서는 접근 불가)
      • public: 기본 클래스에서 public으로 선언된 멤버는 public 상속을 통해 파생 클래스에서도 public으로 접근할 수 있다. (즉, Dog 클래스의 인스턴스에서 접근 가능)
        • 기본클래스의 모든 public, protected 멤버들은 파생 클래스의 public, protected멤버가 됨
        • 기본클래스의 private 멤버는 private 멤버로 남고, 파생 클래스의 의해서 접근될 수 없다.

 

 

▷ public 상속 접근제어로 상속

#include <iostream>
using std::cout;
using std::endl;

class A            // 기본 클래스
{
	int x;  //private:
public:
	void setX(int i) { x = i; }
	void showX() { cout << x << endl; }
};
class B :public A //파생 클래스
{
	int y;
public:
	void setY(int i) { y = i; }
	void showY() { cout << y << endl; }
};
int main()
{
	B bb; // 파생클래스의 객체
	bb.x = 1; // 오류 ① bb.setX(1);  //부모의 private는 접근 불가능
	bb.y = 2; // 오류 ② bb.setY(2);
	bb.showX(); // 기본클래스의 멤버접근
	bb.showY(); // 파생클래스의 멤버접근
	return 0;

}

 

 

▷ public 상속 접근제어로 상속2

#include <iostream>
using std::cout;
using std::endl;
class A
{
	int x;
public:
	void setX(int i) { x = i; }
	void showX() { cout << x << endl; }
};

class B :public A
{
	int y;
public:
	void setY(int i) { y = i; }
	void
		showXY() { cout << x << y << endl; }  //x에서 오류 발생 : 자식이 부모의 private에 접근해서
};

int main()
{
	B bb;
	bb.setX(1); // 기본클래스의 멤버접근
	bb.setY(2); // 파생클래스의 멤버접근
	bb.showX(); // 기본클래스의 멤버접근
	bb.showXY(); // 파생클래스의 멤버접근
	return 0;
}
class B :public A
{
	int y;
public:
	void setY(int i) { y = i; }
	void
		showXY() { cout << showX << y << endl; }  //오류 수정
};

 

 

2) private 상속 접근제어

- private으로 상속하게되면 그대로 상속되는것이 아니고 자식의 private로 상속이 됨.

 

#include <iostream>
using std::cout;
using std::endl;
class A
{
	int x; //int x=10; //가능?
public:
	void setX(int i) { x = i; }
	void showX() { cout << x << endl; }
};

class B :private A //비공개적으로 상속
{
	int y;
	// private 상속을 하면 이쪽. 부모에서 public이었던 것도 자식의 private에 상속되기 때문에 외부에서 접근 불가능
public:
	void setY(int i) { y = i; }
	void showY() { cout << y << endl; }
};

int main()
{
	A aa;
	B bb;
	aa.setX(1);
	aa.showX();
	//bb.setX(1); // 오류
	bb.setY(2); // 파생클래스의 멤버접근
	//bb.showX(); // 오류
	bb.showY(); // 파생클래스의 멤버접근
	return 0;
}

 

- private 상속을 하면 부모에서 public이었던 것도 자식의 private에 상속되기 때문에 외부에서 접근 불가능

 

 

▶ In-class member initializer

#include <iostream>
using std::cout;
using std::endl;
class A
{
	int x = 1; // In-class member initializers 초기값을 이렇게 줄 수도 있다
public:
	void setX(int i) { x = i; }
	int getX() { return x; }
};
int main()
{
	A a1; //디폴트 생성자 호출, 눈에 안보이는 A(){}
	cout << a1.getX() << endl;
	return 0;
}

 

 

#include <iostream>
using std::cout;
using std::endl;
class A
{
	int x = 1;
public:
	A() { x = 2; } // 옆 코드와 같은 소스임.  A():x(2){}
	void setX(int i) { x = i; }
	int getX() { return x; }
};
int main()
{
	A a1; //디폴트 생성자는 사라짐
	cout << a1.getX() << endl;  // 2 출력
	return 0;
}

 

A() { x = 2; }    =    A():x(2){}

 

 

 

3) protected  상속 제어접근

public vs , proticted

공통점 : 외부에서 접근이 바로 안된다.

 

 

▷ 상속에서 생성자와 소멸자

#include <iostream>
using std::cout;
class A
{
public:
	A() { cout << "A의 생성자\n"; }
	~A() { cout << "A의 소멸자\n"; }
};
class B :public A
{
public:
	B() { cout << "B의 생성자\n"; }
	~B() { cout << "B의 소멸자\n"; }
};
int main()
{
	B ob;
	return 0;
}
//실제 B 클래스의 구성
class B :public A
{
public:
	A() { cout << "A의 생성자 "; }
	~A() { cout << "A의 소멸자 "; }
	B() { cout << "B의 생성자 "; }
	~B() { cout << "B의 소멸자 "; }
};

 

부모 클래스 생성자 -> 자식 클래스 생성자

자식 클래스 생성자 -> 부모 클래스 생성자

 

 

▷ 파생 클래스 생성자에서 기본 클래스 생성자에 매개변수 전달 형식

#include <iostream>
using std::cout;
using std::endl;
class A {
	int a;
public:
	A(int i) {
		cout << "A의 생성자\n";
		a = i;
	}
	~A() { cout << "A의 소멸자\n"; }
	void showA() { cout << a << '\n'; }
};

class B :public A {
	int b;
public:
	B(int i, int j) :A(i) {// i는 기본클래스 생성자의 매개변수로 전달
		cout << "B의 생성자\n";
		b = j;
	}
	~B() { cout << "B의 소멸자\n"; }
	void showB() { cout << b << endl; }
}; 


int main()
{
	B bb(10, 20);
	bb.showA();
	bb.showB();
	return 0;
}

 

 

4) 계층적 다중 상속

- 자식 클래스가 여러 개의 기본 클래스를 상속 받을 수 있다.

- 할아버지 클래스로부터 아버지 클래스를 상속 받고, 아버지 클래스로부터 자식 클래스가 상속

#include <iostream>
using std::cout;
using std::endl;
class A //할아버지
{
	int a;
public:
	A(int i) { a = i; }
	int getA() { return a; }
};

class B :public A //아버지
{
	int b;
public:
	B(int i, int j) :A(i) {
		// i는 기본 클래스 A의
		//생성자 매개변수로 전달됨
		b = j;
	}
	int getB() { return b; }
};

class C :public B //자식
{
	int c;
public:
	C(int i, int j, int k) :B(i, j) {
		// i, j는 클래스 B의 생성자 매개변수로 전달됨
		c = k;
	}
	void show() {
		cout << getA() << ' ' << getB() << ' ' << c << endl;
	}
};


int main()
{
	C cc(10, 20, 30);
	cc.show();
	cout << cc.getA() << ' ' << cc.getB() << endl;
	return 0;
}
//10 20 30 
//10 20 
//출력

 

 

5) 여러 개 의 기본 클래스를 동시에 상속

- 아버지와 어머니 클래스를 아들 클래스가 물려 받는 것 ( java, c#, svift 등에선 지원하지 않음 대신 비슷하게 동작하는 다른 게 있음)

▷ 2개의 기본 클래스 상속

#include <iostream>
using std::cout;
using std::endl;
class A1 // 아버지
{
	int a;
public:
	A1(int i) { a = i; }
	int getA() { return a; }
};

class A2 // 어머니
{
	int b;
public:
	A2(int i) { b = i; }
	int getB() { return b; }
};

class B :public A1, public A2
{
	// 기본 클래스 A1과 A2로부터
	// 상속 받은 파생 클래스
	int c;
public:
	B(int i, int j, int k) :A1(i), A2(j) { c = k; }
	// i는 기본클래스 A1의 생성자로,
	// j는 기본클래스 A2의 생성자로
	// 각각 매개변수 전달
	void show() {
		cout << getA() << ' ' << getB() << ' ' << c << endl;
	}
};


int main()
{
	B bb(1, 2, 3);
	bb.show();
	return 0;
}
// 1 2 3  출력

 

 

 

 

//둘다 사람이고 이름이 있네? -> 사람 클래스를 먼저 만들어서 이름과 나이 넣고 자식으로 학생과 교수를 만들어야겠다.

 

- Man 클래스 생성

#include <iostream>
using std::cout;
using std::endl;
using std::string;

//사람클래스(Man, 멤버변수:이름, 나이)를 만드시오.
class Man {
protected:
	string name;
	int age;
};

//멤버변수를 초기화하는 생성자를 구현하시오.
//기타 함수를 구현하시오.
//사람클래스로부터 상속받은 학생클래스(Student)를 만드시오. (멤버변수:반, 학번), 생성자, 기타함수
//사람클래스로부터 상속받은 교수(Teacher)클래스를 만드시오. (멤버변수:전공, 담당과목), 생성자, 기타함수
//main함수에서 학생객체와, 교수객체를 만들어 테스트해보시오.

//int main()
//{
//	Student kks("김컴소", 20, "C반", "202012000");
//	Teacher hsh("한미소", 40, "전산", "C++프로그래밍");
//	kks.s_show();
//	hsh.t_show();
//	return 0;
//}

 

 

- 생성자 구형, 기타함수 구현 -> 부모클래스 완성

#include <iostream>
using std::cout;
using std::endl;
using std::string;

//사람클래스(Man, 멤버변수:이름, 나이)를 만드시오.
class Man {
protected:
	string name;
	int age;
public:
	Man(string n, int a) {  //멤버변수를 초기화하는 생성자를 구현하시오.
		name = n;
		age = a;
	}
	void m_show() {  //기타 함수를 구현하시오. -> show()
		cout << "이름 : " << name << endl;
		cout << "나이 : " << age << endl;
	}
};

//사람클래스로부터 상속받은 학생클래스(Student)를 만드시오. (멤버변수:반, 학번), 생성자, 기타함수
//사람클래스로부터 상속받은 교수(Teacher)클래스를 만드시오. (멤버변수:전공, 담당과목), 생성자, 기타함수
//main함수에서 학생객체와, 교수객체를 만들어 테스트해보시오.

//int main()
//{
//	Student kks("김컴소", 20, "C반", "202012000");
//	Teacher hsh("한미소", 40, "전산", "C++프로그래밍");
//	kks.s_show();
//	hsh.t_show();
//	return 0;
//}

 

 

- Student 클래스 완성

#include <iostream>
using std::cout;
using std::endl;
using std::string;

//사람클래스(Man, 멤버변수:이름, 나이)를 만드시오.
class Man {
protected: //상속할거라서 protected
	string name;
	int age;
public:
	Man(string n, int a) {  //멤버변수를 초기화하는 생성자를 구현하시오.
		name = n;
		age = a;
	}
	void m_show() {  //기타 함수를 구현하시오. -> show()
		cout << "이름 : " << name << endl;
		cout << "나이 : " << age << endl;
	}
};

//사람클래스로부터 상속받은 학생클래스(Student)를 만드시오. (멤버변수:반, 학번), 생성자, 기타함수
class Student : public Man {
private:
	string ban;
	string hak;
public:
	Student(string n, int a, string b, string h) : Man(n,a) {
		ban = b;
		hak = h;
	}
	void s_show() {
		m_show();
		cout << "반 : " << ban << endl;
		cout << "학번 : " << hak << endl;
	}
};

//사람클래스로부터 상속받은 교수(Teacher)클래스를 만드시오. (멤버변수:전공, 담당과목), 생성자, 기타함수
class Teacher : public Man {

};
//main함수에서 학생객체와, 교수객체를 만들어 테스트해보시오.

int main()
{
	Student kks("김컴소", 20, "C반", "202012000");
//	Teacher hsh("한미소", 40, "전산", "C++프로그래밍");
	kks.s_show();
//	hsh.t_show();
	return 0;
}

//이름: 김컴소
//나이 : 20
//반 : C반
//학번 : 202012000

 

 

#include <iostream>
using std::cout;
using std::endl;
using std::string;

//사람클래스(Man, 멤버변수:이름, 나이)를 만드시오.
class Man {
protected: //상속할거라서 protected
	string name;
	int age;
public:
	Man(string n, int a) {  //멤버변수를 초기화하는 생성자를 구현하시오.
		name = n;
		age = a;
	}
	void m_show() {  //기타 함수를 구현하시오. -> show()
		cout << "이름 : " << name << endl;
		cout << "나이 : " << age << endl;
	}
};

//사람클래스로부터 상속받은 학생클래스(Student)를 만드시오. (멤버변수:반, 학번), 생성자, 기타함수
class Student : public Man {
private:
	string ban;
	string hak;
public:
	Student(string n, int a, string b, string h) : Man(n,a) {
		ban = b;
		hak = h;
	}
	void s_show() {
		m_show();
		cout << "반 : " << ban << endl;
		cout << "학번 : " << hak << endl;
	}
};

//사람클래스로부터 상속받은 교수(Teacher)클래스를 만드시오. (멤버변수:전공, 담당과목), 생성자, 기타함수
class Teacher : public Man {
private:
	string major; // 전공
	string sub;   // 담당 과목
public:
	// 생성자에서 Teacher로 이름을 변경
	Teacher(string n, int a, string m, string s) : Man(n, a) {
		major = m;
		sub = s;
	}
	void t_show() {
		m_show();
		cout << "전공 : " << major << endl;
		cout << "과목 : " << sub << endl;
	}
};
//main함수에서 학생객체와, 교수객체를 만들어 테스트해보시오.

int main()
{
	Student kks("김컴소", 20, "C반", "202012000");
	Teacher hsh("한미소", 40, "전산", "C++프로그래밍");
	kks.s_show();
	hsh.t_show();
	return 0;
}

//이름: 김컴소
//나이 : 20
//반 : C반
//학번 : 202012000
728x90

'C++' 카테고리의 다른 글

13. 바인딩, 오버로딩/오버라이 가상함수  (0) 2024.11.26
11. 함수 중첩, 디폴트 인자  (0) 2024.11.12
8. const 동적 메모리 할당 (new, delete)  (8) 2024.11.05
7. 객체와 멤버, 생성자/소멸자, this 포인터  (0) 2024.10.29
6. 접근 속성 클래스와 객체 만들기  (2) 2024.10.15
  1. - 객체지향언어의의 특징 3가지
  2. 1. 상속(inheritance)
  3. 1) public 상속 접근제어
  4. 2) private 상속 접근제어
  5. ▶ In-class member initializer
  6. 3) protected  상속 제어접근
  7. 4) 계층적 다중 상속
  8. 5) 여러 개 의 기본 클래스를 동시에 상속
'C++' 카테고리의 다른 글
  • 13. 바인딩, 오버로딩/오버라이 가상함수
  • 11. 함수 중첩, 디폴트 인자
  • 8. const 동적 메모리 할당 (new, delete)
  • 7. 객체와 멤버, 생성자/소멸자, this 포인터
리버윤
리버윤
기록기록
River_yun기록기록
리버윤
River_yun
리버윤
전체
오늘
어제

공지사항

  • 분류 전체보기 (82)
    • C++ (20)
    • DB (3)
    • Java (5)
    • Swift (13)
    • JavaScript (17)
    • 소프트웨어 설계 (1)
    • iOS프로그래밍 실무 (7)
    • 빅데이터 (1)
    • 기타 (5)

인기 글

블로그 메뉴

  • 홈
  • 태그
250x250
hELLO · Designed By 정상우.
리버윤
12. 상속 (inheritance)
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.