상속은 기존 클래스의 특성(데이터 멤버, 멤버 함수) 를 가져와서 새로운 클래스로 만드는 것이다. 새로운 클래스는 다른 특성도 포함해서 만들 수 있다.
1. 기존 클래스 => 부모 클래스
2. 새로운 클래스 => 자식 클래스
추가적으로 한단계로 이루어진 부모 자식관계를 직접 상속 관계라 한다.
또한 두단계 이상으로 이루어진 관계는 간접 상속 관계라 한다.
한 자식이 여러 부모의 클래스에서 상속 받는 것이 가능한데, 이는 C++만 가능하다.(다중 상속 허용 가능)
우선, 상속에 대해 알기 전에 접근 제한자에 대해 알아보는 것이 좋다.
- private => 오직 클래스 안에서만 접근 가능하다. 예를 들어서, 상속을 통해서 부모 클래스의 private 변수를 가져오고 싶다면 부모 클래스에서 get함수를 통해 가져와야한다.
- protected => 자신을 상속하는 클래스까지만 접근 가능.
외부에서는 접근이 안되지만, 상속되어지는 자식 클래스에서는 이를 사용 가능하다. 따라서, 부모 클래스에서 private로 선언되어 있는 멤버 변수를 protected 로 바꾼다면 get함수를 사용하지 않더라도 바로 사용 가능하다.
- public => 어떤 클래서에서든 접근 가능하다.
자식 클래스 : 접근 제한자 부모 클래스
{
자식 클래스 내용
}
방법은 이러한데, 여기서 중요한 점은 접근 제한자 부분이다. 상속을 할 때, 어떠한 접근 제한자를 쓰는냐에 따라서 사용 범위가 정해진다.
- public > 2. protected > 3. private
private
로 상속을 받는다면, 아래와 같이 축소된다.protected
로 상속을 받는다면, 아래와 같이 축소된다.public
로 상속을 받는다면, 아래와 같이 축소된다.#include<iostream>
using namespace std;
class A {
private:
int a{1};
protected:
int b{2};
public:
int c{3};
};
class B :public A {
void showB() {
//성공 => protected는 자식에서 사용 가능
cout << b << endl;
}
};
int main() {
B example;
//오류 (private 변수)
cout << example.a << endl;
//오류 (proteced 변수)
cout << example.b << endl;
//성공 (public 변수)
cout << example.c << endl;
return 0;
}
위에 코드의 경우 public으로 받았기 떄문에, 아래와 같이 된다.
- private => private
- protected => protected
- public => public
따라서 a,b 는 오류가 생긴다. showB()는 protected 변수를 사용할 수 있다.
#include<iostream>
using namespace std;
class A {
private:
int a{1};
protected:
int b{2};
public:
int c{3};
};
class B :protected A {
void showB() {
//성공 => protected는 자식에서 사용 가능
cout << b << endl;
}
};
int main() {
B example;
//오류 (private 변수)
cout << example.a << endl;
//오류 (proteced 변수)
cout << example.b << endl;
//오류 (public 변수)
cout << example.c << endl;
return 0;
}
위에 코드의 경우 public으로 받았기 떄문에, 아래와 같이 된다.
- private => private
- protected => protected
- public => protected
다른 건 1번 코드와 같고, 하나 다른점은 c가 메인함수에서 출력이 안된다는 점이다. 이는 protected를 통해 상속을 받아서, public 변수가 protected로 축소된 것이다.
#include<iostream>
using namespace std;
class A {
private:
int a{1};
protected:
int b{2};
public:
int c{3};
};
class B :private A {
public:
void showB() {
//성공 => 아래 추가 설명
cout << b << endl;
}
};
int main() {
B example;
example.showB();
return 0;
}
위에 코드의 경우 public으로 받았기 떄문에, 아래와 같이 된다.
- private => private
- protected => protected
- public => public
여기서 주의해야 될점은 protected가 private 으로 축소 되었다면 자식 클래스에서 멤버 함수에서 부모클래스의 멤버 변수를 사용 못하는 것이 아니냐는 의문이 있을 수 있다.
하지만, 자식 클래스에선 private로 상속되었다고 해서, 바로 자식 클래스 안에서 private로 바뀌는 것이 아니다.
이 자식 클래스를 사용할때, 그 변수들이 private로 바뀌는 것이다.
따라서 자식 클래스 선언에선 부모 클래스에서의 제한자를 따르며, 이후에 자식 클래스를 사용할때, 선언해준 제한자를 따른다고 정리하면 될 것 같다.
부모 클래스에서의 변수를 자식 클래스에서 바로 받을 순 없다. 아래 코드와 같이 진행할 경우, 접근할 수 없다고 나오며 오류를 발생하게 된다.
#include<iostream>
using namespace std;
class A {
private:
int a{ 1 };
int b{ 2 };
int c{ 3 };
public:
void showAdd() {
cout << a << endl << b << endl << c << endl;
}
};
class B :public A {
public:
void showA() {
//오류 => a를 접근할 수 없음.
cout << a << endl;
}
};
그렇다면 어떻게 접근해야 할까? 두가지 방법이 있다.
#include<iostream>
using namespace std;
class A {
private:
int a{ 1 };
int b{ 2 };
int c{ 3 };
public:
//get함수를 통해 private변수 접근
int getA() { return a; }
void showAdd() {
cout << a << endl << b << endl << c << endl;
}
};
class B :public A {
public:
void showA() {
cout << getA() << endl;
}
};
두번째 방법은 멤버변수를 protected로 바꾸어주는 것이다.
그렇게 함으로써 자식 클래스에서 사용 가능하게 해준다.
#include<iostream>
using namespace std;
class A {
//protected로 선언하면서 자식에서 사용 가능하게 한다.
protected:
int a{ 1 };
int b{ 2 };
int c{ 3 };
public:
void showAdd() {
cout << a << endl << b << endl << c << endl;
}
};
class B :public A {
public:
void showA() {
cout << a << endl;
}
};