본문 바로가기
C++

C++프로그래밍 12주차

by asd135 2023. 11. 22.
728x90

 

인스턴스 aa가 접근할 수 있는 멤버변수 목록

 

#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 {

};

int main() {
    A aa;
    aa.b1();
    B bb;
    bb.b1();
}

 

상속 방법

자식 클래스 : 접근 제어자 부모 클래스 

A클래스의 public을 B클래스에 상속했으므로 bb.b1(); 가능하다

 


프로그래밍 언어들의 상속 방법

 

c++

class Base {
public:
    void baseFunction() {}
};

class Derived : public Base {
public:
    void derivedFunction() {}
};

 

java

class Base {
    public void baseFunction() {}
}

class Derived extends Base {
    public void derivedFunction() {}
}

 

c#

class Base {
    public void BaseFunction() {}
}

class Derived : Base {
    public void DerivedFunction() {}
}

 

python

class Base:
    def baseFunction(self):
        pass

class Derived(Base):
    def derivedFunction(self):
        pass

 

 


상속 구조

 

 

 


상속 접근제어

 

 

-private멤버는 상속불가

-부모클래스의 (public, protected) 멤버가 자식클래스로 넘어온다.

-3가지 상속 속성중에서 public을 가장 많이 씀

 


예제

 

B클래스가 A클래스를 상속 받았음

 

#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(2); // 오류 ② bb.setY(2);
	bb.showX(); // 기본클래스의 멤버접근
	bb.showY(); // 파생클래스의 멤버접근
	return 0;
}

 

private멤버는 상속 불가

bb.setX(1); 부모클래스 private 값을 변경

 

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

 

부모의 private멤버 접근은 get함수를 써야함

 


상속 속성이 private인 경우

 

private멤버는 상속 불가

public, protected 멤버는 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;
}

 

오류 나는 이유는 private으로 상속해서 외부에서 접근 할 수 없고 자식클래스 내부에서만 사용 가능하다.

 

private 속성으로 상속받은 자식클래스는 부모클래스의 함수를 내부에서만 사용할 수 있다. 


클래스 내부에서 멤버변수 초기화 방법(비추)

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

 

생성자 정의 방법

1. A() { x = 2; }

2. A():x(2){}

 


protected 상속

 


 

protected 접근제어속성 특징

-자식에게 상속됨

-외부에서 접근 할 수 없음

 

private속성은 멤버변수를 상속 할 수 없지만 protected속성은 멤버변수를 상속 할 수 있으므로 상속을 할 경우 protected속성으로 하는것이 좋음

 

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

 


가장 많이 사용하는 방식

 

 


상속에서 생성자와 소멸자

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

 

생성자는 부모의 생성자가 호출되고 자식의 생성자가 호출된다.

소멸자는 자식의 소멸자가 호출되고 부모의 소멸자가 호출된다. 

 

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

 

#include <iostream>
using std::cout;
using std::endl;
class B { //할아버지
	double d;
public:
	B(double dd) { d = dd; }
	double getD() { return d; }
};
class D1 :public B { //아버지
	int i;
public:
	D1(double dd, int ii) :B(dd) { i = ii; }
	int getI() { return i; }
};
class D2 :public D1 { //자식
	char c;
public:
	D2(double dd, int ii, char cc) :D1(dd, ii) { c = cc; }
	void print() {
		cout << "Double : " << getD() << endl;
		// B 멤버 호출
		cout << "Int : " << getI() << endl;
		// D1 멤버 호출
		cout << "Char : " << c << endl;
	}
};
int main()
{
	D2 d2(10.5, 10, 'H');
	cout << d2.getD() << ',' << d2.getI() << endl;
	// B, D1 멤버 호출
	d2.print();
	return 0;
}

 

 

이 소스는 한성현 교수님 소스를 수정했습니다.

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

C++ 프로그래밍 14주차  (1) 2023.12.06
C++프로그래밍 13주차  (1) 2023.11.29
C+프로그래밍 11주차  (0) 2023.11.15
C++프로그래밍 10주차  (0) 2023.11.08
C++ 프로그래밍 9주차  (0) 2023.11.01