public 상속과 private 상속의 차이점?

nayana의 이미지

문법책을 보다가 의문점이 생겨서 질문을 드립니다.
다름아니라...
A class, B class 있다고 했을 때...
A class 가 기반 클래스 B class 가 파생 클래스 일때...
class B : public A
일때 B클래스에서 protected는 A class에 protected, public 멤버에 접근할수 있고 외부에서는 A class의 public , B class의 public에 접근 할수 있고
class B: private A
일때 B클래스에서 protected는 A class에 protected, public 멤버에 접근할
수 있고 외부에서는 A class의 public에 접근할수없고 B class의 public에 접근할수가 있다고 나옵니다.그래서 나름대로 시험을 해볼려고 실험을 해봤습니다.
a.h

     1 #ifndef __A_H__
      2 #define __A_H__
      3
      4 class A
      5 {
      6 public :
      7     A();
      8     virtual ~A();
      9     void Init();
     10
     11 protected :
     12     void Init1();
     13
     14 private :
     15     void Init2();
     16 };
     17
     18 #endif

a.cpp
      1 #include "a.h"
      2 #include <cstdio>
      3
      4 A::A()
      5 {
      6 }
      7
      8 A::~A()
      9 {
     10
     11 }
     12
     13 void A::Init()
     14 {
     15     printf( "A public\n" );
     16 }
     17
     18 void A::Init1()
     19 {
     20     printf( "A protected\n" );
     21 }
     22
     23 void A::Init2()
     24 {
     25     printf( "A private\n" );
     26 }

b.h
      1 #ifndef __B_H__
      2 #define __B_H__
      3
      4 #include "a.h"
      5
      6 class B: private A
      7 {
      8 public :
      9     B();
     10     virtual ~B();
     11     void bInit();
     12
     13 protected:
     14     void bInit1();
     15
     16 private:
     17     void bInit2();
     18 };
     19
     20 #endif

b.cpp
      1 #include "b.h"
      2 #include <cstdio>
      3
      4 B::B()
      5 {
      6
      7 }
      8
      9 B::~B()
     10 {
     11 }
     12
     13 void B::bInit()
     14 {
     15     printf( "B public\n" );
     16     bInit1();
     17 }
     18
     19 void B::bInit1()
     20 {
     21     A::Init(); // 접근 가능
     22     A::Init1(); // 접근 가능
     23     printf( "B protected\n" );
     24 }
     25
     26 void B::bInit2()
     27 {
     28     printf( "B private\n" );
     29 }

c.h
     1 #ifndef __C_H__
      2 #define __C_H__
      3
      4 #include "a.h"
      5
      6 class C
      7 {
      8 public :
      9     C();
     10     ~C();
     11     void cInit();
     12 protected :
     13     void cInit1();
     14 private :
     15     void cInit2();
     16     A a;
     17 };
     18
     19 #endif

c.cpp
      1 #include "c.h"
      2 #include <cstdio>
      3
      4 C::C()
      5 {
      6
      7 }
      8
      9 C::~C()
     10 {
     11
     12 }
     13
     14 void C::cInit()
     15 {
     16     a.Init(); // 이론대로 하면 여기서 접근 불가능이라고 나와야 하는데..접근 가능합니다.
     17     printf( "C public\n" );
     18 }
     19
     20 void C::cInit1()
     21 {
     22     printf( "C protected\n" );
     23 }
     24
     25 void C::cInit2()
     26 {
     27     printf( "C private\n" );
     28 }

main.cpp
         1 #include "b.h"
      2 #include "c.h"
      3
      4 int main( void )
      5 {
      6     B b;
      7     C c;
      8
      9     b.bInit();
     10     c.cInit();
     11
     12     return 0;
     13 }

외부( C class ) 에서 A class의 public 에 외부접근 되는데...책이 잘못된건 가요...아니면...제가 상속에 대해서 잘못 이해하고 있는건가요? 아무래도 제가 잘못이해하고 있는것 같은데....^^
익명 사용자의 이미지

이그.. 의도하지 않게 클래스를 재정의 해버렸네요...
B, C 클래스 멤버함수가 없으면 A 클래스 멤버를 상속받게 되지요..

bugiii의 이미지

C 클래스는 A 클래스를 포함하고 있습니다. C 클래스는 A 클래스를 상속한게 아니므로, C 에서 A 를 포함하면 C 멤버안에서는 A 의 public 멤버를 사용할 수 있습니다.

상속과 포함을 잠깐 혼동하신 듯 합니다.

아마 C 클래스에 B 클래스를 포함하고 B 를 통한 A 멤버의 접근이 안되는 경우를 말씀하시려고 하신 것 같습니다.

public, private 상속은 그 성격이 판이하게 다르기 때문에 꼭 좋은 텍스트를 참고하시면 좋겠습니다.

yielding의 이미지

헤깔리고 계시네요.

C와 A는 아무 상속관계없고 클래스 C에서 private member의 public member함수를 호출하고 있으니 아무 문제 없습니다.

TC++PL에 아주 자세히 잘 설명 되어 있습니다.

Life rushes on, we are distracted

nayana의 이미지

일단 답변에 감사드립니다.
아마 C 클래스에 B 클래스를 포함하고 B 를 통한 A 멤버의 접근이 안되는 경우를 말씀하시려고 하신 것 같습니다
님의 말씀대로 c.h 파일에 B class 인스턴스 b 를 선언하고

    14 void C::cInit()
     15 {
     16     b.bInit();
     17     printf( "C public\n" );
     18 }

다음과 같이 하였습니다. 이렇게 하였을 경우 C class는 B class public 에 접근 가능하므로 당연히 잘됩니다. C Class에 B클래스 인스턴스 선언하여
A class의 public 어떻게 접근해야하는지요 그리고 접근했을때 접근이 안되야하는데??????그리고 위의코드도 B를 통한 A멤버의 접근이 아닌가요?
bugiii의 이미지

nayana 님은 지금 상속과 포함을 혼동하고 계십니다. C 클래스에 뭔가를 포함시켰다는 것은 C 에서 그것을 자유롭게 사용하고 싶다는 것을 나타내기도 합니다. C 에 포함시키고서도 C 안에서 사용하지 못하도록 하는 것은 이상하지요?

다시 만드신 예제도 C 에 B 를 포함한 것입니다. 여기서 C 내부에서 B 의 public 멤버를 이용(!)한다는 것은 아무런 하자가 없는 합법적인 행동입니다. 설령 B 가 A 를 상속을 (private 이든 public 이든) 하고 A 의 public, proteced 멤버를 사용한다 하더라도 C 에서는 상관하지 않습니다. B 가 합법적으로 A 를 사용하고 있고 그 멤버가 외부로 노출된다면 C 에서 B 의 그 멤버를 사용하는 것은 아무런 문제가 없습니다.

지금 말씀하시고자 하는 것은 C 외부에서 C 를 사용하는 입장에서 C 내부의 A, B 중 일부는 열고 일부는 막고자 하는 것인가요? 이런 경우는 C 의 외부 인터페이스를 그에 맞게 권한설정을 하시고 만드셔야 합니다.

private, protected, public 의 키워드가 같이 사용되어서 같은 의미라고 생각하지 마시고 상속은 상속, 멤버의 권한은 권한 이렇게 분리해서 찬찬히 곰곰히 생각해보시고 책도 보시면 "아!하!" 하는 순간이 오실겁니다.

무엇을 할 것인지 정확하게 정하시고 도전해보시는 것이 혼동에서 벗어날 수 있는 유일한 길...

nayana의 이미지

책에 이렇게 나와있습니다.
그 후대 클래스나 자식 클래스의 객체, 즉 자식 클래스의 외부에서는 외부의 클래스의 모든 멤버가 private가 되기때문에 접근권한을 갖지 못한다.
이말의 의미가 이중상속 받았을때...B클래스가 부모 class를 private로 받았기때문에...
가령 예를 들어서 class C: private B, or class C: public B,
class C: protected B 로 받았을때 B클래스가 A 클래스를 private로 받았기
때문에...안되는걸로 알고 있습니다. 이거는 당연히 B클래스가 부모를 private로 상속하였기때문에...당연히 안되는데.....제가 궁금한것은 그 후대의 클래스뿐만 아니라...자식 클래스의 객체 또한 그렇다고 하여...의문을 갖고 접근하고 있습니다.

bugiii의 이미지

nayana wrote:
책에 이렇게 나와있습니다.
그 후대 클래스나 자식 클래스의 객체, 즉 자식 클래스의 외부에서는 외부의 클래스의 모든 멤버가 private가 되기때문에 접근권한을 갖지 못한다.
이말의 의미가 이중상속 받았을때...B클래스가 부모 class를 private로 받았기때문에...
가령 예를 들어서 class C: private B, or class C: public B,
class C: protected B 로 받았을때 B클래스가 A 클래스를 private로 받았기
때문에...안되는걸로 알고 있습니다. 이거는 당연히 B클래스가 부모를 private로 상속하였기때문에...당연히 안되는데.....제가 궁금한것은 그 후대의 클래스뿐만 아니라...자식 클래스의 객체 또한 그렇다고 하여...의문을 갖고 접근하고 있습니다.

네 만약 B 클래스의 객체를 하나 만들고 그 객체를 이용하는 곳에서 A 의 멤버를 호출할 수 없다는 것은 맞습니다. 즉 위의 코드를 다음과 같이 시험하면

    B b;
    b.Init(); // A의 멤버를 B 객체를 사용하는 곳에서 사용하면 불법

컴파일 에러가 나지 않던가요?

하지만, 예로 드신 코드들은 모두 A 나 B 를 포함하고 있지 않습니까? 그리고 B 로 만든 객체도 B 의 공개된 멤버만을 외부에서 호출하고 있지 A 의 멤버를 호출하고 있지는 않습니다.

좀 더 하시다보면, 상속에서 다양한 표현 방법이 있다는 것을 아시게 될 것입니다. 숙달되면 관용구처럼 사용하는 패턴들이 있습니다. 이런 것은 경험을 하시고 체득하셔야 하는 것이니 너무 조급하게 생각하지 마시고 천천히 하지만 정확하게 공부하시기를 바랍니다.

nayana의 이미지

감사 합니다. 제가 잠시 착각을 했난 봅니다.
제가 너무 한심스러워 보이는 군요...
정말로 답변 감사드립니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.