C++ 상속(Inheritance)

다른 여타의 객체지향언어와 같이 C++ 역시 상속을 할 수 있습니다. 여러분은 현실 생활에서 상속이라는 개념을 알고있으신가요? 부모님으로부터 100억을 상속을 받으셨다면 이 포스팅을 볼 필요없으십니다. 저랑 친구해요.

객체지향 프로그래밍에서는 부모 클래스의 맴버 변수와 메소드를 자식 클래스가 재사용하는 개념으로 알고 계시면 됩니다. 이 맴버 변수나 메소드에 접근 제한자를 더하여 아무나 접근할 수 없도록 할 수 있습니다. C++에서 상속하는 방법은 ' : ' 콜론을 사용하여 상속을 받을 수 있습니다. JAVA에서 extends를 사용하여 상속을 하는 것과 같습니다. 형식은 아래와 같습니다.

class 클래스_이름 : 접근제한자 부모_클래스명{
	//.. 내용 ..//
}

 

접근 제한자

접근 제한자는 세가지가 있습니다. private, protected, public이라는 접근 제한자가 있지요. 

접근 제한자 설명
private 오직 자신의 클래스안에서만 접근 가능한 멤버 변수, 메소드.
protected 자신을 상속하는 클래스까지만 접근 가능
public 어떤 클래스에서나 접근 가능

접근 범위

 

생성자 (Constructor)

클래스가 객체를 생성할때 항상 호출하는 일종의 메소드가 있습니다. 이 메소드는 생성자라는 이름을 갖고 있습니다. 여러분이 객체를 생성할때 초기화하는 방법을 생성자에 기재합니다. 이를 테면, 각 맴버 변수들의 초기화 등이 있지요. 형식은 아래와 같습니다. 자신의 클래스명과 동일하지만 반환이 없는 메소드가 바로 생성자입니다.  생성자를 사용하려면 반드시 public으로 해야합니다. 모든 곳에서 접근 가능해야 초기화를 진행할 수 있기 때문이죠. 

여러분들이 굳이 생성자를 정의해놓지 않아도 C++은 알아서 기본 생성자(Default Constructor) 만들어줍니다. 비록 아무런 동작을 하지 않는 껍데기에 불과하지만요.

class 클래스명 {
public :
	클래스명(파라미터){
    	//..동작 ..//
    }
}

 

소멸자(Destructor)

소멸자는 객체가 소멸할때 마지막 최종작업을 기록하는 메소드를 말하며 아래 형식과 같습니다. 소멸자는 반환값, 전달받는 인자가 없고 ~클래스이름() 형태여야합니다. 주로 free, delete 등의 메모리 누수가 발생하지 않게 메모리 해제 작업등이 여기에 포함됩니다.

class A{
public:
	~A(){
    	//..메모리 해제등의 작업 ..//
    }
}

 

 

 

이제 여기서 간단한 예를 들어보도록 하겠습니다. 

#include <iostream>
using namespace std;

class A {
private:
	int a;
	int b;
public:
	A(int _a, int _b){
		a = _a;
		b = _b;
	}
	int add() {
		return a + b;
	}
};

class B : A {
public :
	B(int _a, int _b) : A(_a, _b) {}
	void printResult() {
		//A를 상속받았으니, 부모클래스의 add라는 메소드를 사용할 수 있음.
		printf("%d\n", add());
	}
};

int main() {
	B b(1, 2);
	b.printResult();
}

 

A는 자신만이 접근한 맴버 변수 a와 b를 가지고 있습니다. 그리고 생성자를 갖고 있는데, 여기서 a와 b를 초기화시켜줍니다. 그리고 누구나 접근 가능한(public) 메소드 add를 갖고 있습니다. 이 메소드는 단순 a와 b를 더한 값을 전달하지요. 맴버를 초기화할 수 있는 방법은 이런 방법도 있습니다. 

public :
	A(int _a, int _b):a(_a),b(_b) {
		
	}

B는 A 클래스를 부모 클래스(또는 Super Class라고 합니다.)로 상속을 받습니다. 이때 부모 클래스의 초기화를 하는 방법은 : 부모클래스명(매개변수명1, 매개변수명2 ...)으로 초기화 시킬 수 있습니다. 자, 여기서 눈여겨 보셔야할 점은 B는 A클래스를 상속받았기 때문에 a와 b는 갖고 있지만, 접근할 수 없습니다. 

printResult라는 메소드에서는 add()라는 메소드를 사용할 수 있는데 A의 클래스에서 정의하고 public으로 접근할 수 있게 만들었기 때문에 B클래스에서 사용할 수 있습니다.

접근 제한자를 통한 상속

우리는 위의 예제에서 접근 제한자는 따로 지정하지 않고 상속을 받았습니다. 상속받는 부분에서 접근 제한자를 지정하게 되면 부모 클래스의 맴버 변수, 메소드를 지정한 접근 제한자보다 범위가 넓은 맴버 변수, 메소드에 접근할 수가 없습니다. public을 명시적으로 지정해주어야만 다형성의 속성을 사용할 수 있습니다.

private 상속 

#include <iostream>
using namespace std;

class A {
private:
	int a;
protected:
	int b;
public:
	int c;
};

class B : private A { //b,c맴버 변수는 private 맴버로 접근 범위 졻혀짐

};


int main() {
	B b;
    //a = private, b = private, c = private
	b.a;
	b.b;
	b.c;
}

 

 

 

B는 A를 private로 상속받습니다. A의 맴버변수 b,c는 private보다 범위가 넓으므로 b,c는 private로 제한합니다. 따라서 a,b,c 모두 접근할 수 없습니다.

protected 상속

#include <iostream>
using namespace std;

class A {
private:
	int a;
protected:
	int b;
public:
	int c;
};

class B : protected A { //c맴버 변수는 protected 맴버로 접근 범위 졻혀짐

};


int main() {
	B b;

	//a = private, b = protected, c = protected
	b.a;
	b.b;
	b.c;
}

A의 맴버 변수 중에 protected보다 범위가 넓은 맴버는 protected로 접근이 제한됩니다.

public 상속

#include <iostream>
using namespace std;

class A {
private:
	int a;
protected:
	int b;
public:
	int c;
};

class B : public A { //맴버 변수의 접근 제한에 변화없음

};


int main() {
	B b;

	//a = private, b = protected, c = public
	b.a;
	b.b;
	b.c;
}

public보다 접근 제한이 넓은 맴버는 public으로 맞춰지는데, 의미없죠? public보다 큰 제한자는 없으니까요. 

 

캡슐화(Encapsulation)

캡슐화라는 것은 맴버 변수를 직접 변경할 수 없도록 캡슐처럼 껍데기를 둘러싸는 과정을 말합니다. 캡슐안에서 특정 로직에 따라 맴버 변수가 적절하게 변경되어야 프로그램이 안전할 수 있기 때문이죠. 아래의 코드가 그 예를 보여줍니다.

#include <iostream>
using namespace std;

class A {
private:
	int a;
	int b;
public:
	void setA(int _a) {
		if (_a > 50)
			_a = 50;
		a = _a;
	}
	void setB(int _b) {
		if (_b > 100)
			_b = 100;
		b = _b;
	}

	int getA() {
		return a;
	}
	int getB() {
		return b;
	}
};

class B : A {
public :
	void setAB(int a,int b) {
		setA(a);
		setB(b);
	}
	void printResult() {
		printf("%d + %d = %d\n", getA(), getB(), getA() + getB());
	}
};


int main() {
	B b;
	b.setAB(100, 200);
	b.printResult();
}

 

간단한 코드인데요. B는 A를 상속받습니다. 이때 a,b는 직접 설정할 수 없게 private로 접근을 제한했구요. 메인 함수에서는 b에서 setAB를 호출해서 a의 값을 100, b의 값을 200으로 바꾸려고 합니다. 하지만 A 클래스는 그것을 용납하지 않습니다. a의 최대값은 50, b의 최대값은 100으로 제한을 해놓았기 때문이죠. B가 a와 b를 변경할 수 있는 수단은 A 클래스의 setA와 setB를 호출하여 인자 전달을 하는 방법밖에 없습니다. 이렇게 맴버의 값을 함부로 변경할 수 없도록 맴버 함수로 껍질을 입히는 작업을 캡슐화라고 합니다. 이렇게 Get, Set 메소드를 Getter, Setter메소드라고 합니다.

객체지향 언어에서 반드시 필요한 속성임을 기억하세요.

 

 

반응형
블로그 이미지

REAKWON

와나진짜

,