C++ private 상속

프로그래밍/C++ 2019.10.24 댓글 Plorence

private 상속은 기초 클래스의 public 멤버protected 멤버가 파생 클래스의 private 멤버가 됩니다.

public 상속도 기초 클래스의 public 멤버와 protected 멤버가 파생 클래스의 public 멤버가 된 겁니다.

has-a 관계를 모델링하는 방법 중 나머지 한 가지의 방법이 private 상속입니다.

 

파생 클래스는 기초 클래스의 인터페이스를 상속하는 것이 is-a관계의 역할이었지만

private상속은 파생 클래스가 기초 클래스의 인터페이스를 상속하지 않습니다.

상속이 안 되는 것은 has-a관계의 역할입니다.

 

컴포지션(컨테인먼트)과 다른 점

컨테인먼트는 객체를 이름이 있는 멤버 객체로 클래스에 추가하지만 private상속은 객체를 이름이 없는 상속된 객체로 클래스에 추가합니다.

그래서 접근하려면 그 클래스의 이름으로 접근을 해야 합니다.

private 상속을 하려면 항상 쓰던 public 대신에 private를 사용하면 됩니다.

(접근 제한자를 생략하면 디폴트가 private이기 때문에 private로 됩니다.)

 

초기화

초기화는 이름이 없기 때문에 멤버 초기자 리스트를 사용할 때 클래스명을 써야 합니다.

class Student : private valarray<double> { //private 상속
public:
        Student() : valarray<double>(3) { //멤버 초기자 리스트로 초기화
        }
};

 

기초 클래스 멤버 함수에 접근

기초 클래스 멤버함수에 접근하려면 사용 범위 결정 연산자를 사용해 접근해야 합니다.

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <valarray>
using namespace std;
class Student : private valarray<double> {
public:
        Student() : valarray<double>(3) { //멤버 초기자 리스트로 초기화
        }
        int GetSize() { //배열의 원소 갯수를 리턴하는 멤버함수
               return valarray<double>::size();
        }
};
int main(void) {
        Student stu = Student();
        cout << stu.GetSize(); //3이 출력된다!!
}

 

기초 클래스 객체에 접근

강제 데이터형 변환을 하면 됩니다.

class Student : private valarray<double> {
public:
        Student() : valarray<double>(3) { //멤버 초기자 리스트로 초기화
        }
        const valarray<double> & GetArray() {
               return (const valarray<double> &)*this;
        }
};

 

프렌드

class Student : private valarray<double> {
public:
        Student() : valarray<double>(3) { //멤버 초기자 리스트로 초기화
        }
        friend const valarray<double> & GetArray(const Student & stu);
};
const valarray<double> & GetArray(const Student & stu) {
        return (const valarray<double> &)stu;
}

프렌드도 기초 클래스 객체에 접근할 때처럼 똑같이 하면 됩니다.

자동으로 변환이 되지 않는 이유는 private상속에서 명시적인 데이터형 변환이 없으면 파생 클래스에 대한 참조나 포인터를 기초 클래스에 대한 참조나 포인터에 대입할 수 없기 때문입니다.(강제 데이터형 변환이 반드시 필요함.)

 

컨테인먼트 방식과 private 상속 중 선호도는?

대부분의 C++ 프로그래머는 컨테인먼트를 선호합니다.

  • 사용하기 쉽기 때문이다.(명시적으로 이름이 지정되어 있다.)

  • 상속이 문제를 일으킬 수 있다.(하나의 객체밖에 사용할 수 없고, 같은 이름을 가진 멤버 함수를 사용하고 있을 때의 문제와 같은 것들을 해결해야 하는 일이 생길 수 있음.)

private상속이 필요한 상황

protected멤버를 파생 클래스에서 사용(접근) 해야 할 때 해당 클래스가 내포된 객체로 되면 protected멤버로 접근이 불가능합니다.

#include <iostream>
class A {
protected:
       int value = 0;
};
class Student {
       A a;
public:
       int getValue() {
              return a.value; //에러!
       }
};

왜냐면 내포된 클래스는 파생 클래스가 아니라 클래스 멤버의 일부가 되기 때문입니다.

이러한 이유로 상속을 통해 이러한 문제점이 해결이 됩니다.(protected멤버는 상속되면 파생 클래스에서 사용할 수 있기 때문)

#include <iostream>
class A {
protected:
       int value = 0;
};
class Student : private A {
public:
       int getValue() {
              return A::value; //문제 없음
       }
};

가상 함수

가상 함수는 파생 클래스와 관련 있는 건데 private상속을 사용하면 다시 정의된 함수들을 public으로 사용할 수 없고 그 클래스 안에서만 사용할 수 있습니다.

 

댓글