두 class가 서로를 이용할때

lacovnk의 이미지

class A;
class B;
class A
{
 B b;
}
class B
{
 A a;
}

이런 경우가 생길지 몰랐습니다 -o-

문제는 class A 정의시 안에서 B가 incomplete하다고 투덜대는데, 내부를 볼 필요도 없는데 어째서 그런가요?

해결방법이 궁금합니다. 뭐라 검색해야 할지 모르겠군요 -o-

forward declaration이 적용이 안되는건가요? 음음

byung82의 이미지

인터페이스 활용에 한표 드립니다.

class IA
{
public:
virtual void Hellow() = 0;
}

class B
{
private:
IA *a;
}

class A
: public IA
{
}

이런씩으로

그럼

chadr의 이미지

class A 
{ 
 B b; 
} 
class B 
{ 
 A a; 
}

이 경우는 불가능 할 것 같군요..

음... A라는 클래스를 정의 하기 위해서는 A라는 클래스가 B라는 클래스를 맴버로 가지기 때문에 B라는 클래스의 완벽한 정의가 필요합니다.. 그런데 B라는 클래스를 정의 하기 위해서는 A라는 클래스를 맴버로 가지기 때문에 A라는 클래스의 완벽한 정의가 필요합니다..

...

모순이지요..

-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

ixevexi의 이미지

lacovnk wrote:
class A;
class B;
class A
{
 B b;
}
class B
{
 A a;
}

이런 경우가 생길지 몰랐습니다 -o-

문제는 class A 정의시 안에서 B가 incomplete하다고 투덜대는데, 내부를 볼 필요도 없는데 어째서 그런가요?

해결방법이 궁금합니다. 뭐라 검색해야 할지 모르겠군요 -o-

forward declaration이 적용이 안되는건가요? 음음


포인터를 쓰세용..
그럼 될듯 합니다 ^^
class A
{
B * b;
};
class B
{
A * a;
};

이런식으로요..

C++, 그리고 C++....
죽어도 C++

powereyes의 이미지

static/dynamic scope 개념으로 생각을 해봐도 되나 모르겠네요.

static scope 에서는

class A 
{ 
 B b; 
} 

는 불가능하고,

dynamic scope 에서는 compiler 구현하기 나름이지 않을지..;

lovemyin의 이미지

Quote:
포인터를 쓰세용..
그럼 될듯 합니다 ^^

이 방법이 가장 좋을듯 한데요... 많이 쓰이는 방법이기도 하고요

/***************************************************
* 가장 심플한 것이 가장 아름다운 것이다.
***************************************************/

쌀밥의 이미지

상호참조 문제군요.

상호 참조의 경우 대부분 설계의 문제에서 발생한다고 Andrei씨의 책에서 본것 같습니다.

A가 B를 사용하고 B가 A를 사용한다면
이 둘은 각각 독립된 모듈로 볼 수 없고 하나의 덩어리 패키지로 봐야하는데
이 것은 모듈화나 캡슐화와 관련된 설계의 부실일 수가 있으니
설계를 점검해보시길 권합니다.

그리고 상호 참조의 문제는 앞의 분들이 언급해주셨듯이 포인터로 하면 해결이 되지만
미리 컴파일된 헤더의 이점을 얻는데 걸림돌로 남게 됩니다.

일하는 사람들의 희망 민주노동당 : http://www.kdlp.org
반공 교육의 성과로, 민주주의의 반대가 공산주의(또는 사회주의)라고 생각하는 사람이 많다.

pok의 이미지

상호참조랑 조금 관련있는것 같아서 질문올립니다.

같은 헤더파일내에서

class Pcb {
	public:
		int Data;
		Pcb* next;
};

//container class : queue
class Queue {
	public:
		Queue(){pHead_ = pTail_ = NULL;}
		//~Queue();
		void add(Pcb* _pPcb); //포인터라도 참조하고 있는것이 선언되어 있지 않으면 에러를 낸다.
		//헤더파일 이용순서를 잘 알아야 겠다.
		Pcb* giveBack();
		//Pcb* giveBackIt(QueueIterator* _pItr);
		//QueueIterator createIterator();
		Pcb* pHead_;//to test
	private:
		//Pcb* pHead_;
		Pcb* pTail_;
};

이건 되는데
//container class : queue
class Queue {
	public:
		Queue(){pHead_ = pTail_ = NULL;}
		//~Queue();
		void add(Pcb* _pPcb); //포인터라도 참조하고 있는것이 선언되어 있지 않으면 에러를 낸다.
		//헤더파일 이용순서를 잘 알아야 겠다.
		Pcb* giveBack();
		//Pcb* giveBackIt(QueueIterator* _pItr);
		//QueueIterator createIterator();
		Pcb* pHead_;//to test
	private:
		//Pcb* pHead_;
		Pcb* pTail_;
};

class Pcb {
	public:
		int Data;
		Pcb* next;
};

이건 컴파일에러를 냅니다.
C에 익숙해서 선언을 몽땅 한 헤더에 해버리고 각각의 정의를 파일별로 하려고 했는데, C++은 좀 다른 헤더정책이 필요한것 같습니다.
(C에서는 선언만하고 정의를 하지 않아도 되는데 C++에서는 안되는것 같더군요. scaffolding 만들때 의외로 귀찮습니다 -_-)
제가 잘못한것은 무엇이고, C++에서의 좋은 헤더파일 관리는 어떤것일까요?
ixevexi의 이미지

pok wrote:
상호참조랑 조금 관련있는것 같아서 질문올립니다.

같은 헤더파일내에서

class Pcb {
	public:
		int Data;
		Pcb* next;
};

//container class : queue
class Queue {
	public:
		Queue(){pHead_ = pTail_ = NULL;}
		//~Queue();
		void add(Pcb* _pPcb); //포인터라도 참조하고 있는것이 선언되어 있지 않으면 에러를 낸다.
		//헤더파일 이용순서를 잘 알아야 겠다.
		Pcb* giveBack();
		//Pcb* giveBackIt(QueueIterator* _pItr);
		//QueueIterator createIterator();
		Pcb* pHead_;//to test
	private:
		//Pcb* pHead_;
		Pcb* pTail_;
};

이건 되는데
//container class : queue
class Queue {
	public:
		Queue(){pHead_ = pTail_ = NULL;}
		//~Queue();
		void add(Pcb* _pPcb); //포인터라도 참조하고 있는것이 선언되어 있지 않으면 에러를 낸다.
		//헤더파일 이용순서를 잘 알아야 겠다.
		Pcb* giveBack();
		//Pcb* giveBackIt(QueueIterator* _pItr);
		//QueueIterator createIterator();
		Pcb* pHead_;//to test
	private:
		//Pcb* pHead_;
		Pcb* pTail_;
};

class Pcb {
	public:
		int Data;
		Pcb* next;
};

이건 컴파일에러를 냅니다.
C에 익숙해서 선언을 몽땅 한 헤더에 해버리고 각각의 정의를 파일별로 하려고 했는데, C++은 좀 다른 헤더정책이 필요한것 같습니다.
(C에서는 선언만하고 정의를 하지 않아도 되는데 C++에서는 안되는것 같더군요. scaffolding 만들때 의외로 귀찮습니다 -_-)
제가 잘못한것은 무엇이고, C++에서의 좋은 헤더파일 관리는 어떤것일까요?

제일 앞에 class Pcb;
이거 하나만 넣어주면 되는듯 합니다.
말씀 하신대로 저것이 선언이고
class Pcb{
~~};
는 정의 아니었나요?

C++, 그리고 C++....
죽어도 C++

paperplane의 이미지

class Pcb 의 정의가 "pcb.h" 에 있다고 할 때

Pcb 클래스를 사용하는 클래스에서

단순히 Pcb 클래스를 참조만 한다면

(예를 들어, 지역 변수나 매개 변수로만 사용한다면...)

코드 앞에
class Pcb;

라고 선언하면 되지만,

만약 참조만 하는 것이 아니라 Pcb 클래스를 사용하는 것이라면,

(예를 들어 Pcb 클래스의 내부 메소드나 속성 등에 접근해야 할 필요가 있다면..)

이 때는 참조하고자 하는 클래스의 정의를 알아야 하는 것이므로

헤더파일을 포함해야 할 필요가 있습니다.

#include "pcb.h"

익명 사용자의 이미지

ixevexi wrote:

제일 앞에 class Pcb;
이거 하나만 넣어주면 되는듯 합니다.
말씀 하신대로 저것이 선언이고
class Pcb{
~~};
는 정의 아니었나요?

아. 그렇군요.. 감사합니다.
더욱더 헤더의 난해한 세상에 좌절하고 있습니다. 으억.
lacovnk의 이미지

사용하다가 매우 곤란한 경우를 경험했습니다.

서로의 생성자가 계속 서로를 call.. -o-

당연한 결과긴 한데.. 참 조심해서 써야겠군요. 으음..

애초부터 이런 설계가 옳지 못한 것일까요?

쌀밥의 이미지

pok wrote:
C에 익숙해서 선언을 몽땅 한 헤더에 해버리고 각각의 정의를 파일별로 하려고 했는데, C++은 좀 다른 헤더정책이 필요한것 같습니다.
(C에서는 선언만하고 정의를 하지 않아도 되는데 C++에서는 안되는것 같더군요. scaffolding 만들때 의외로 귀찮습니다 -_-)
제가 잘못한것은 무엇이고, C++에서의 좋은 헤더파일 관리는 어떤것일까요?

저는 C++를 몇년간 쓰면서 C와 헤더파일 사용법이 다르다는 점을 느끼지 못했습니다.
C++ 에서도 헤더에 선언만 하고 정의는 안해도 됩니다.
헤더 파일 관리는 C와 같은 방법으로 충분하다고 생각합니다.

그리고 상호 참조에 관한 좀 더 자세한 정보를 알고 싶으시다면
Andrei 씨의 "Modern C++ Design"이라는 책 (번역본 있음)에서 visitor 패턴 관련 부분을 참고하세요.

그리고 include 를 줄이고 컴파일 타임을 줄이는 방법에 대해서는 "Exceptional C++" (번역본 있음)에서 잘 다루고 있습니다.
참고하세요.

일하는 사람들의 희망 민주노동당 : http://www.kdlp.org
반공 교육의 성과로, 민주주의의 반대가 공산주의(또는 사회주의)라고 생각하는 사람이 많다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.