C++

12주차 강의내용

wlsn 2024. 11. 19. 13:40

aa.을 하면 class A에 있는 public부분에 b1~b4까지 나타낼 수 있다.

 

B는 아무것도 없기때문에 나타나지 않는다.

 

하지만 상속을 한다면 부모의 public을 물려받을 수 있다.

 

C++, JAVA, python의 상속 예제다.

 

C++

#include <iostream>
using std::cout;

class Animal { // 기본 클래스
public:
    void speak() { cout << "Animal speaks\n"; } // 기본 클래스의 메서드
};

class Dog : public Animal { // 파생 클래스
public:
    void speak() { cout << "Dog barks\n"; } // 오버라이드된 메서드
};

int main() {
    Animal a;
    a.speak(); // 출력: Animal speaks

    Dog d;
    d.speak(); // 출력: Dog barks

    return 0;
}

 

JAVA

class Animal { // 기본 클래스
    void speak() {
        System.out.println("Animal speaks"); // 기본 클래스의 메서드
    }
}

class Dog extends Animal { // 파생 클래스
    void speak() {
        System.out.println("Dog barks"); // 오버라이드된 메서드
    }
}

public class Main {
    public static void main(String[] args) {
        Animal a = new Animal();
        a.speak(); // 출력: Animal speaks

        Dog d = new Dog();
        d.speak(); // 출력: Dog barks
    }
}

 

python

class Animal:  # 기본 클래스
    def speak(self):
        print("Animal speaks")  # 기본 클래스의 메서드

class Dog(Animal):  # 파생 클래스
    def speak(self):
        print("Dog barks")  # 오버라이드된 메서드

if __name__ == "__main__":
    a = Animal()
    a.speak()  # 출력: Animal speaks

    d = Dog()
    d.speak()  # 출력: Dog barks

 

 

상속관계는 다른말로 is a 관계라고도 볼 수 있다.

 

부모클래스에서 public으로 상속받은 자식클래스라고 읽을 수 있다.

 

상속의 접근 제어는 파생 클래스에서 기본 클래스의 멤버에 대한 접근 권한을 정의합니다.
public 상속을 통해 protected와 public 멤버는 파생 클래스에서 그대로 접근할 수 있게 됩니다.

대체로 public 상속은 C++에서 가장 많이 사용되는 상속 형태이며, 많은 개발자들이 기본 클래스의 기능을 확장하고 재사용하기 위해 이를 선택합니다. 그러나 특정 상황에서는 protected나 private 상속이 더 적합할 수 있습니다. 따라서, 실제 비율은 프로젝트나 개별 개발자의 스타일에 따라 다를 수 있습니다.

 

상속이되면 public으로 한다고해도 private은 절때로 넘어가지않고 protected와 public은 넘길 수 있다.

 

#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 showY() { cout << y << endl; }
};
int main()
{
	B bb; // 파생클래스의 객체
	bb.setX(1); // 오류 ① bb.setX(1);
	bb.setY(1); // 오류 ② bb.setY(2);
	bb.showX(); // 기본클래스의 멤버접근
	bb.showY(); // 파생클래스의 멤버접근
	return 0;
}

private은 상속도 안되며 각 class에서만 사용할 수 있다.

 

부모의 public을 통해서 접근을 할 수 있다.

 

private 상속은 protected나 public이 protected나 public으로 갔던 것을 모두 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;
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;
}

setX에 경우 private으로 가기 때문에 bb.setX(1);을 불러온다면 private으로 외부에서 접근하는 것이기 때문에 오류가 뜰 수 밖에 없다.

 

 

왼쪽 소스에서 빨간부분 = 1을 뺀다면 쓰레기 값이 출력된다.

 

#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;
	return 0;
}

public부분에 A()는 두 생성자는 같다고 볼 수 있다. 시험에 꼭 출제된다고 함.

 

protected는 잘 사용하지 않지만 protected와 public이 둘다 protected로 간다. 하지만 거의 쓰지 않는 상속법.

 

private과 protected의 공통점은 외부에서 접근이 불가능하다. 고로 public으로 접근해야 함.

 

a,b는 "자식"이외 외부에서 접근 불가, a,b가 자식에게 상속안됨, a,b는 A클래스 내에서 접근 가능

 

protected 접근제어의 장점

 

1. 상속 관계에서의 접근 허용
protected 멤버는 기본 클래스의 파생 클래스에서 접근할 수 있습니다. 이를 통해 기본 클래스의 기능을 확장하면서도 멤버 변수를 보호할 수 있습니다.


2. 캡슐화 유지
protected는 외부 클래스나 함수에서는 접근할 수 없지만, 상속받은 클래스에서는 접근할 수 있기 때문에, 클래스를 사용하는 외부 코드와 내부 구현을 분리하여 캡슐화를 유지할 수 있습니다.

 

3. 유연성 제공
파생 클래스에서 기본 클래스의 protected 멤버를 사용할 수 있어, 기본 클래스의 기능을 재사용하고 확장하는 데 유리합니다. 이는 코드의 유연성을 높입니다.

 

4. 다형성 지원
protected 멤버는 다형성을 구현할 때 유용합니다. 파생 클래스에서 기본 클래스의 protected 멤버를 오버라이드하거나 사용하여, 더 구체적인 동작을 정의할 수 있습니다.

 

5. 정보 은닉
외부에서 직접 접근할 수 없기 때문에, 데이터의 안전성을 유지하면서도 상속받은 클래스에서 필요한 기능을 사용할 수 있습니다. 이는 불필요한 데이터 노출을 방지합니다.

 

#include <iostream>
using std::cout;
using std::endl;
class A
{
protected: //private이라면?
	int a, b;
public:
	void setAB(int i, int j) { a = i; b = j; }
};
class B :public A
{
	int c; // private
public:
	void setC(int n) { c = n; }
	void showABC() { cout << a << b << c << endl; }
	//기본 클래스의 protected 멤버들은
	//파생 클래스의 멤버에 의해 접근될 수 있다.
};
int main()
{
	A aa;
	B bb;
//	aa.a; //외부에서는 접근불가
//	bb.b; //외부에서는 접근불가
	bb.setAB(1, 2);
	bb.setC(3);
	bb.showABC();
	return 0;
}

main부분에 aa.a와 bb.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:
    // A의 생성자를 호출하기 위해 초기화 목록 사용
    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); // B 객체 생성
    bb.showA();  // A의 멤버 출력
    bb.showB();  // B의 멤버 출력
    return 0;
}

A의 생성자부분을 먼저 가져와야하기 때문에 A(i)부분을 뺀다면 오류가 난다.

 

#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;
}

 

#include <iostream>
using std::cout;
class A1 // 기본 클래스 1
{
	int a;
public:
	A1() { cout << "A1의 생성자.\n"; }
	~A1() { cout << "A1의 소멸자.\n"; }
};
class A2 // 기본 클래스 2
{
	int b;
public:
	A2() { cout << "A2의 생성자.\n"; }
	~A2() { cout << "A2의 소멸자.\n"; }
};
class B : public A2, public A1
	// 기본 클래스 1과 2로부터
	// 상속 받은 파생 클래스
{
	int c;
public:
	B() { cout << "B의 생성자.\n"; }
	~B() { cout << "B의 소멸자.\n"; }
};
int main()
{
	B bb;
	return 0;
}

class B : public A1, public A2를 서로 바꿔서 쓴다면 부모가 바뀔 수 있다.

 

학생과 교수 class

 

1단계

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

int main()
{

	return 0;
}

 

2단계

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

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

 

3단계

#include <iostream>
using std::cout;
using std::endl;
//사람클래스(Man, 멤버변수:이름, 나이)를 만드시오.
//멤버변수를 초기화하는 생성자를 구현하시오.
//기타 함수를 구현하시오.
class Man {
protected:
	std::string name;
	int age;//멤버변수 완성
};
//사람클래스로부터 상속받은 학생클래스(Student)를 만드시오.
//(멤버변수:반, 학번), 생성자, 기타함수
//사람클래스로부터 상속받은 교수(Teacher)클래스를 만드시오.
//(멤버변수:전공, 담당과목), 생성자, 기타함수
//main함수에서 학생객체와, 교수객체를 만들어 테스트해보시오.

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

 

4단계

#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; } //생성자는 class 이름과 같다.
};
//사람클래스로부터 상속받은 학생클래스(Student)를 만드시오.
//(멤버변수:반, 학번), 생성자, 기타함수
//사람클래스로부터 상속받은 교수(Teacher)클래스를 만드시오.
//(멤버변수:전공, 담당과목), 생성자, 기타함수
//main함수에서 학생객체와, 교수객체를 만들어 테스트해보시오.

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

생성자 만들기

 

5단계

#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; } //생성자는 class 이름과 같다.
	void m_show() {
		cout << "이름 : " << name << endl;
		cout << "나이 : " << age << endl;
	}
};
//사람클래스로부터 상속받은 학생클래스(Student)를 만드시오.
//(멤버변수:반, 학번), 생성자, 기타함수
//사람클래스로부터 상속받은 교수(Teacher)클래스를 만드시오.
//(멤버변수:전공, 담당과목), 생성자, 기타함수
//main함수에서 학생객체와, 교수객체를 만들어 테스트해보시오.

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

m_show를 만들고 부모 class 완성

 

6단계

#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; } //생성자는 class 이름과 같다.
	void m_show() {
		cout << "이름 : " << name << endl;
		cout << "나이 : " << age << endl;
	}
};
class Student : public Man { // public Man으로 상속받기
private:
	string ban;
	string hak;
public:
	Student(string n, int a, string b, string h) : Man(n,a) { ban = b, hak = h; }
};
//사람클래스로부터 상속받은 학생클래스(Student)를 만드시오.
//(멤버변수:반, 학번), 생성자, 기타함수
//사람클래스로부터 상속받은 교수(Teacher)클래스를 만드시오.
//(멤버변수:전공, 담당과목), 생성자, 기타함수
//main함수에서 학생객체와, 교수객체를 만들어 테스트해보시오.

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

 

7단계

#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; } //생성자는 class 이름과 같다.
	void m_show() {
		cout << "이름 : " << name << endl;
		cout << "나이 : " << age << endl;
	}
};
class Student : public Man { // 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;
	}
};
//사람클래스로부터 상속받은 학생클래스(Student)를 만드시오.
//(멤버변수:반, 학번), 생성자, 기타함수
//사람클래스로부터 상속받은 교수(Teacher)클래스를 만드시오.
//(멤버변수:전공, 담당과목), 생성자, 기타함수
//main함수에서 학생객체와, 교수객체를 만들어 테스트해보시오.

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

 

8단계

#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; } //생성자는 class 이름과 같다.
	void m_show() {
		cout << "이름 : " << name << endl;
		cout << "나이 : " << age << endl;
	}
};
class Student : public Man { // 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;
	}
};
class Teacher : public Man { // public Man으로 상속받기
private:
	string jaun;
	string dam;
public:
	Teacher(string n, int a, string j, string d) : Man(n, a) { jaun = j, dam = d; }
	void t_show() {
		m_show();
		cout << "전공 : " << jaun << endl;
		cout << "담당과목 : " << dam << endl;
	}
};
//사람클래스로부터 상속받은 학생클래스(Student)를 만드시오.
//(멤버변수:반, 학번), 생성자, 기타함수
//사람클래스로부터 상속받은 교수(Teacher)클래스를 만드시오.
//(멤버변수:전공, 담당과목), 생성자, 기타함수
//main함수에서 학생객체와, 교수객체를 만들어 테스트해보시오.

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

	kks.s_show();
	hsh.t_show();
	return 0;
}

총 완성형의 모습이다.

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

13주차 강의 내용  (0) 2024.11.26
13주차 예습과제  (0) 2024.11.26
12주차 예습과제  (0) 2024.11.18
11주차 강의 내용  (0) 2024.11.12
11주차 예습과제  (0) 2024.11.11