정적 멤버 변수에 대해...

icanfly의 이미지

다른 클래스의 인스턴스를 정적 멤버로 가지는 클래스를 다음과 같이 만들었는데...전방 선언부에서 에러를 내네요.

#include <iostream>
using namespace std;

여기와===>class TempObject;

class ClassFactory
{
private:
	short m_iRefCount;
public:
	ClassFactory(void):m_iRefCount(0) {}
여기===>	TempObject* CreateObject(short i){ ++m_iRefCount; return new TempObject(i); }
	short GetRefCount(void){ return m_iRefCount; }
};

class TempObject
{
private:
	short m_iUniqID;
public:
	TempObject(short i) : m_iUniqID(i) {}
	short GetUniqID(void){ return m_iUniqID; }
	static ClassFactory m_Factory;
};

ClassFactory TempObject::m_Factory;

int main(void)
{
	TempObject* pObjTemp1, *pObjTemp2;
	
	pObjTemp1 = TempObject::m_Factory.CreateObject(3);
	short i = pObjTemp1->m_Factory.GetRefCount();
	
	cout << i << endl;
	
	pObjTemp2 = TempObject::m_Factory.CreateObject(4);
	i = pObjTemp2->m_Factory.GetRefCount();
	
	cout << i << endl;
	
	delete pObjTemp1, pObjTemp2;
	
	return 0;
}

에러메세지는

--------------------Configuration: ClassFactory - Debug--------------------
Compiling source file(s)...
ClassFactory.cpp
ClassFactory.cpp: In member function `TempObject*
ClassFactory::CreateObject(short int)':
ClassFactory.cpp:12: error: invalid use of undefined type `struct TempObject'
ClassFactory.cpp:4: error: forward declaration of `struct TempObject'

ClassFactory.exe - 2 error(s), 0 warning(s)

이렇군요. Mingw에서 컴파일 했는데....전방 선언같은건 잘 안쓰는 문법이라.

익숙치 않아서 그런지...... 저런 에러 메세지는 잘 처리를 못하겠네요.

어디가 잘못된것인지..조언 부탁드리겠습니다. 그럼..

bugiii의 이미지

TempObject의 포인터형을 리턴하는 것까지는 전방참조로 해결할 수 있지만 정작 CreateObject 함수 안에서 new 연산자를 이용해서 TempObject 의 인스턴스를 만들어야 하므로 TempObject가 무엇인지 정확하게 알아야 한다고 불평하는 것입니다...

그렇다고 TempObject 정의를 ClassFactory위에 다 할 수 없는 것이 TempObject안에 ClassFactory를 포인터나 리퍼런스가 아닌 그대로 포함하고 있기 때문에 마찬가지 이유로 그렇게 할 수 없습니다.

설계를 다시 한번 고민해 보셔야 할 듯 합니다.... :wink: 팩토리 패턴에 관련된 좋은 텍스트들이 많으니까 꼭 참고하시구요...

icanfly의 이미지

전방선언은 추상적인 형식을 선언하는 그이상의 의미는 없는 거였군요.

그렇게 많은 고민을 해서 적은 코드는 아니고, 이제까지 클래스 팩토리는

외부의 독립된 객체로 존재하고 있다가, 다른 객체를 생성시킨다고만 알고 있었는데. 어떤 코드를 보니 위 처럼 static멤버로 각 클래스마다 구체적인 멤버를 하나씩 포함 시켜서 구현한 것도 있는거 같아서 비슷하게 나마 해보려고 대충 끄적여 본겁니다.

역시 실력이란, 이런 기초적인 코드를 하나 하나 적어보면서 늘어 나는게 아닌가 싶습니다. 요즘은 다들 너무 UI 따라하기 류의 책들이 쏟아지는거 같아서..

답변 감사했습니다. 그럼..

Testors의 이미지

#include <iostream> 
using namespace std; 

class TempObject; 

class ClassFactory 
{ 
private: 
   short m_iRefCount; 
public: 
   ClassFactory(void):m_iRefCount(0) {} 
   TempObject* CreateObject(short i);
   short GetRefCount(void){ return m_iRefCount; } 
}; 

class TempObject 
{ 
private: 
   short m_iUniqID; 
public: 
   TempObject(short i) : m_iUniqID(i) {} 
   short GetUniqID(void){ return m_iUniqID; } 
   static ClassFactory m_Factory; 
}; 

ClassFactory TempObject::m_Factory; 

TempObject* ClassFactory::CreateObject(short i) {++m_iRefCount; return new TempObject(i); } 

int main(void) 
{ 
   TempObject* pObjTemp1, *pObjTemp2; 
    
   pObjTemp1 = TempObject::m_Factory.CreateObject(3); 
   short i = pObjTemp1->m_Factory.GetRefCount(); 
    
   cout << i << endl; 
    
   pObjTemp2 = TempObject::m_Factory.CreateObject(4); 
   i = pObjTemp2->m_Factory.GetRefCount(); 
    
   cout << i << endl; 
    
   delete pObjTemp1, pObjTemp2; 
    
   return 0; 
} 

bugiii 님 말씀대로 TempObject 에 대해 모르기 때문에 new 할수 없다고 하는 것입니다.
이런경우 CreateObject() 함수 구현을 위와 같이 TempObject 밑으로 내리세요..

icanfly의 이미지

제목처럼 정정멤버가 int, char 등이 아니고 어떤사용자 정의 클래스로 부터 인스턴스화 된 변수라면 ...... 코드로 보면 다음과 같을때....

 1 class A
  2 {
  3 public:
  4         int _x;
  5 };
  6
  7 class B
  8 {
  9 public:
 10         static A _temp_a;
 11         static int ii;
 12         int bb;
 13 };
 14
 15 int B::ii = 4;
 16
 17 A B::_temp_a;
 18 B::_temp_a._x = 3;
 19
 20 int main(void)
 21 {
 22         B b;
 23         b._temp_a._x = 4;
 24         return 0;
 25 }

int B::ii = 4; 는 문제없이 값의 대입이 되는데..
B::_temp_a._x = 3; 는 대입이 되지 않네요.
b._temp_a._x = 4; 이렇게 인스턴스를 만들어서 값을 주면되는데...

B 클래스 객체를 만들기전에 B::_temp_a의 _x 멤버에 값을 할당할수는
없는건가요?

Testors의 이미지

icanfly wrote:
제목처럼 정정멤버가 int, char 등이 아니고 어떤사용자 정의 클래스로 부터 인스턴스화 된 변수라면 ...... 코드로 보면 다음과 같을때....

 1 class A
  2 {
  3 public:
  4         int _x;
  5 };
  6
  7 class B
  8 {
  9 public:
 10         static A _temp_a;
 11         static int ii;
 12         int bb;
 13 };
 14
 15 int B::ii = 4;
 16
 17 A B::_temp_a;
 18 B::_temp_a._x = 3;
 19
 20 int main(void)
 21 {
 22         B b;
 23         b._temp_a._x = 4;
 24         return 0;
 25 }

int B::ii = 4; 는 문제없이 값의 대입이 되는데..
B::_temp_a._x = 3; 는 대입이 되지 않네요.
b._temp_a._x = 4; 이렇게 인스턴스를 만들어서 값을 주면되는데...

B 클래스 객체를 만들기전에 B::_temp_a의 _x 멤버에 값을 할당할수는
없는건가요?

간단히 해결해 보자면 이런 방법이 있겠습니다만...

class A
{
public:
    A( int x ) : _x(x) {}
    int _x;
};

class B
{
public:
    static A _temp_a;
    static int ii;
    int bb;
};

int B::ii = 4;

A B::_temp_a(3);

int main(void)
{
    B b;
    b._temp_a._x = 4;
    return 0;
}
icanfly의 이미지

잘되는군요. 값의 대입은 안되도 초기화는 잘되는군요.

초기화로 해볼생각은 하지도 못하고 있었는데 감사합니다.

댓글 달기

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