[문법] 싱글톤패턴 질문입니다.

이소희의 이미지

문법적인 질문입니다.

#include <iostream> 
using namespace std; 

class A { 
public: 
   static A* Instance();   // << 요기 static
   int  getData()     { return data; } 
   void increment()   { data++; } 
private: 
   A() { data=0; } 
   static A* _instance;  // << 요기 static
   int data; 
}; 

위의 클래스에서.
1) static A* Instance();
2) static A* _instance;

위 1),2) 를 생성하는데 static으로 선언하는 이유가 무엇인가요?
쉬운거라 생각드셔도 자세히 설명을 해주셨으면 감사하겠습니다.

doldori의 이미지

static이 의미하는 바는 문맥에 따라 달라지지만, 지금은 '유일함'을 뜻합니다.
즉 A::Instance, A::_instance는 A 개체가 몇 개가 되든지 하나만 존재한다는
뜻입니다. 이 특성이 singleton pattern의 목적과 잘 맞아 떨어지지요.
구현은 대략 다음과 같이 되겠네요.

A* A::_instance = 0;

A* A::Instance()
{
    if (_instance == 0)
        _instance = new A;
    return _instance;
}
pynoos의 이미지

static 을 쓰는 이유는 개체를 만들지 않고도 함수를 호출할 수 있기 때문입니다.

A* a = A::Instance();

이런식으로 사용하는 것이지요. 이렇게 유일한 개체를 받는데 사용합니다.

sjpark의 이미지

static은 클래스 10개가 인스턴스화 되어도, 딱 한개만 있다는 것이지요.
므흣.

atie의 이미지

static-singleton을 쓰면, 클래스의 이름으로 레퍼런스를 하드코드하게 되므로 static method를 override 할 수 없게 됩니다. 그러므로, static method가 final처럼 사용이 됩니다.

----
I paint objects as I think them, not as I see them.
atie's minipage

freezm7의 이미지

atie wrote:
static-singleton을 쓰면, 클래스의 이름으로 레퍼런스를 하드코드하게 되므로 static method를 override 할 수 없게 됩니다. 그러므로, static method가 final처럼 사용이 됩니다.

"static method가 final처럼 사용이 됩니다."

이게 무슨 뜻인가요? 문맥이 전혀 이해가 안되네요.

final은 C가 아니라 java 용어죠?
C에서는 method보단 function이라고 하는게 일반적이구요.

그걸 고려하더라도 무슨 뜻인지 모르겠습니다.
override 할 수 없다는 것도 무슨 뜻인지 모르겠고...

OOP에 나름대로 자신이 있었는데... 아직도 한참 먼 것 같네요.

자세한 설명 부탁드립니다.

즐겁게 살아 볼까나~*

이소희의 이미지

답변해주신 분들 덕분에 더욱 확실히 알되었습니다.
다시한번 감사드립니다. ^^

행복하세요~~~~

내 삶속에 던져진 나.

gimmesilver의 이미지

doldori wrote:
static이 의미하는 바는 문맥에 따라 달라지지만, 지금은 '유일함'을 뜻합니다.

글쎄요...static을 '유일함' 이라고 생각한다는 것은 오해의 소지가 큰 것 같군요...프로그래밍에서 static은 컴파일 타임 바인딩을 뜻하는 것이고 그렇기 때문에 객체에서나 함수 모듈 등에서 '유일함'이라고 오해할 수 있는 특성이 나타나는 것이지 그것이 static을 정의하지는 못한다고 생각합니다...

예를 들어 헤더 파일에 선언된 static 변수는 해당 파일을 포함하는 각각의 파일에 별개의 존재로 바인딩 되죠...이건 컴파일 타임 바인딩으로 생각해야 이해할 수 있는 동작입니다...유일함이라고 생각해서는 안되죠...

------------------------
http://agbird.egloos.com

doldori의 이미지

Agbird wrote:

글쎄요...static을 '유일함' 이라고 생각한다는 것은 오해의 소지가 큰 것 같군요...프로그래밍에서 static은 컴파일 타임 바인딩을 뜻하는 것이고 그렇기 때문에 객체에서나 함수 모듈 등에서 '유일함'이라고 오해할 수 있는 특성이 나타나는 것이지 그것이 static을 정의하지는 못한다고 생각합니다...

static 멤버가 컴파일 타임 바인딩을 갖는다고 말씀하셨는데 static 멤버는
바인딩 자체가 없는 것 아닌가요? 어떤 뜻인지 좀 더 자세하게 설명해주시면
좋겠습니다.

Agbird wrote:

예를 들어 헤더 파일에 선언된 static 변수는 해당 파일을 포함하는 각각의 파일에 별개의 존재로 바인딩 되죠...이건 컴파일 타임 바인딩으로 생각해야 이해할 수 있는 동작입니다...유일함이라고 생각해서는 안되죠...

좀 혼동스럽군요. 혹시 바인딩으로 지칭하시는 것이 실은 linkage를 말씀하시는
것이 아닌가 합니다. 요것도 좀 더 설명을 부탁드립니다.
atie의 이미지

freezm7 wrote:
atie wrote:
static-singleton을 쓰면, 클래스의 이름으로 레퍼런스를 하드코드하게 되므로 static method를 override 할 수 없게 됩니다. 그러므로, static method가 final처럼 사용이 됩니다.

"static method가 final처럼 사용이 됩니다."

이게 무슨 뜻인가요? 문맥이 전혀 이해가 안되네요.

final은 C가 아니라 java 용어죠?
C에서는 method보단 function이라고 하는게 일반적이구요.

그걸 고려하더라도 무슨 뜻인지 모르겠습니다.
override 할 수 없다는 것도 무슨 뜻인지 모르겠고...

OOP에 나름대로 자신이 있었는데... 아직도 한참 먼 것 같네요.

자세한 설명 부탁드립니다.


자바 용어는 양해를 바랍니다. 그리고, singleton의 인스턴스를 리턴하는 static method는 의미상 final 이다 이야기 한 것인데 혼란이 되게끔 적어났군요.

이유인즉, 그 singleton의 static method는 A.getInstance() 이런 식으로 클래스의 이름이 명시가 되어 사용이 되고, base 클래스에 있는 static method는 서브 클래스로 확장해서 override 시킬 수 없습니다. (적어도 자바에서는 이 경우의 다형적 변경을 허용하지 않습니다.) 따라서, singleton의 static method를 다른 클래스에서 바꾸어 사용할 방법이 없으므로 의미상 final이다 라고 적은 겁니다.

또한, method는 public static으로, member는 private static으로 singleton을 적용하는 것도 위의 답변으로 쉽게 이해가 될 듯 하군요. (ensure a class has only one instance, and provide a global point of access to it)

----
I paint objects as I think them, not as I see them.
atie's minipage

gimmesilver의 이미지

doldori wrote:
Agbird wrote:

글쎄요...static을 '유일함' 이라고 생각한다는 것은 오해의 소지가 큰 것 같군요...프로그래밍에서 static은 컴파일 타임 바인딩을 뜻하는 것이고 그렇기 때문에 객체에서나 함수 모듈 등에서 '유일함'이라고 오해할 수 있는 특성이 나타나는 것이지 그것이 static을 정의하지는 못한다고 생각합니다...

static 멤버가 컴파일 타임 바인딩을 갖는다고 말씀하셨는데 static 멤버는
바인딩 자체가 없는 것 아닌가요? 어떤 뜻인지 좀 더 자세하게 설명해주시면
좋겠습니다.

Agbird wrote:

예를 들어 헤더 파일에 선언된 static 변수는 해당 파일을 포함하는 각각의 파일에 별개의 존재로 바인딩 되죠...이건 컴파일 타임 바인딩으로 생각해야 이해할 수 있는 동작입니다...유일함이라고 생각해서는 안되죠...

좀 혼동스럽군요. 혹시 바인딩으로 지칭하시는 것이 실은 linkage를 말씀하시는
것이 아닌가 합니다. 요것도 좀 더 설명을 부탁드립니다.

컴파일 바인딩의 의미는 해당 변수에 대한 속성이 컴파일 타임에 이미 확정된다는 것을 뜻합니다. 그리고 그렇기 때문에 클래스의 static 멤버는 객체의 생성 여부 혹은 그 개수에 상관없이 하나가 되어야 하는 것입니다...(왜냐하면 실행전에는 해당 객체의 생성 여부나 생성 개수를 컴파일러가 알 수 없기 때문입니다.)
바로 이 때문에 '유일함'이라는 특성을 갖는 것이라 혼동할 수 있습니다.
비슷하게 함수 모듈 내에서 사용되는 static 변수 역시 해당 변수의 바인딩이 컴파일 타입에 이루어 지기 때문에 static 변수의 공간적 스코핑은 모듈내로 제한될 수 있지만(컴파일러가 공간 영역은 알 수 있으므로...) 시간 스코핑은 프로그램의 실행 시간 동안 계속 유지 되는 것입니다...(컴파일러는 해당 모듈이 언제, 몇번 실행되는지 모르고 따라서 해당 static 변수를 언제, 그리고 몇 개를 생성해야 하는지 모르므로...)

두번째 예는 아래와 같습니다.

/// test.h
static int nTest = 0;

/// test1.cpp
#include <iostream>
#include "test.h"

using namespace std;

void testFunc();
int main()
{
    nTest = 3;
    cout << nTest << endl;

    testFunc();

    return 0;
}

/// test2.cpp
#include <iostream>
#include "test.h"

using namespace std;
void testFunc()
{
    cout << ++nTest << endl;
}

이것의 결과는 아래와 같습니다.
3
1
왜나하면 test1.cpp와 test2.cpp에서 참조하는 nTest는 이름은 같지만 서로 다른 변수이기 때문입니다. 그리고 그 이유는 컴파일 타임 시 컴파일러는 각각의 소스 파일을 컴파일하면서 별도의 변수로 이미 바인딩을 해버리기 때문입니다. 여기서 만약 test.h 에 있는 nTest를 static으로 선언하지 않고 global로 선언을 하게 되면 링크 단계에서 에러가 발생합니다...왜냐하면 컴파일러는 해당 변수가 중복 선언되었다는 사실을 링크 단계에서 알게 되기 때문입니다...
반대로 static 변수는 extern을 이용해서 파일끼리 공유를 할 수 없습니다. 왜냐하면 extern은 기본적으로 링크 단계에서야 해당 변수에 대한 정확한 바인딩이 가능하기 때문입니다...
이것이 바로 static과 non-static의 차이입니다...

------------------------
http://agbird.egloos.com

doldori의 이미지

Agbird wrote:

컴파일 바인딩의 의미는 해당 변수에 대한 속성이 컴파일 타임에 이미 확정된다는 것을 뜻합니다. 그리고 그렇기 때문에 클래스의 static 멤버는 객체의 생성 여부 혹은 그 개수에 상관없이 하나가 되어야 하는 것입니다...(왜냐하면 실행전에는 해당 객체의 생성 여부나 생성 개수를 컴파일러가 알 수 없기 때문입니다.)
바로 이 때문에 '유일함'이라는 특성을 갖는 것이라 혼동할 수 있습니다.

'속성'이라는 용어가 정확히 어떤 뜻인지 알 수 없군요. type, storage duration,
linkage 등의 잘 정의된 용어가 있으니 이들을 쓰셨으면 제가 이해하기 쉬울
텐데요. 그리고 다음은 표준에서 인용한 것입니다.
Quote:

9.4.2/1
A static data member is not part of the subobjects of a class. There is
only one copy of a static data member shared by all the objects of the class.

표준에서 명시하고 있는 것을 '혼동'이라고까지 말씀하시니 당황스럽습니다.

Agbird wrote:

비슷하게 함수 모듈 내에서 사용되는 static 변수 역시 해당 변수의 바인딩이 컴파일 타입에 이루어 지기 때문에 static 변수의 공간적 스코핑은 모듈내로 제한될 수 있지만(컴파일러가 공간 영역은 알 수 있으므로...) 시간 스코핑은 프로그램의 실행 시간 동안 계속 유지 되는 것입니다...(컴파일러는 해당 모듈이 언제, 몇번 실행되는지 모르고 따라서 해당 static 변수를 언제, 그리고 몇 개를 생성해야 하는지 모르므로...)

짐작대로 바인딩을 linkage의 뜻으로 쓰셨군요. 사실 static의 뜻이 좀 혼란스럽기는
하지요. 그래서 처음에 '문맥에 따라' 달라진다고 했던 거고요. 지금 말씀하시는
문맥에서는 보통 '외부 static 개체는 internal linkage를 갖는다'고 합니다.
(적어도 C++에서는 그렇습니다.) 공간적 스코핑은 scope, 시간 스코핑은
storage duration을 뜻하는 것이 아닌가 다시 짐작해 봅니다.
익명 사용자의 이미지

doldori wrote:

'속성'이라는 용어가 정확히 어떤 뜻인지 알 수 없군요. type, storage duration,
linkage 등의 잘 정의된 용어가 있으니 이들을 쓰셨으면 제가 이해하기 쉬울
텐데요. 그리고 다음은 표준에서 인용한 것입니다.

죄송합니다...제가 공부가 좀 짧다보니 그런 용어를 사용하는데 서툴러서 그렇습니다...다만 제가 예전에 학교다닐때 바인딩이라는 의미가 개체와 속성을 연관시키는 것이라고 배운 기억이 있어서 속성이라는 말을 사용했을 뿐이었습니다...

Quote:

Quote:

9.4.2/1
A static data member is not part of the subobjects of a class. There is
only one copy of a static data member shared by all the objects of the class.

표준에서 명시하고 있는 것을 '혼동'이라고까지 말씀하시니 당황스럽습니다.

맞습니다. 클래스의 멤버로 사용된 static 변수는 하나만 생성되는 것이 맞지요...제가 지적하려고 했던 것은 그것을 부정하겠다는 것이 아니라 그것이 static 이 가지고 있는 의미 자체가 아니라는 점을 강조하려 했던 것입니다...
c++표준에서 클래스의 static 멤버가 유일한 객체가 될 수 밖에 없는 이유는 말그대로 정적 바인딩이 이루어지기 때문이라는 점을 강조하고 싶었던 것입니다...'혼동'이라는 표현을 사용한 것은 제가 좀 성급했었군요...

Quote:

짐작대로 바인딩을 linkage의 뜻으로 쓰셨군요. 사실 static의 뜻이 좀 혼란스럽기는
하지요. 그래서 처음에 '문맥에 따라' 달라진다고 했던 거고요. 지금 말씀하시는
문맥에서는 보통 '외부 static 개체는 internal linkage를 갖는다'고 합니다.
(적어도 C++에서는 그렇습니다.) 공간적 스코핑은 scope, 시간 스코핑은
storage duration을 뜻하는 것이 아닌가 다시 짐작해 봅니다.

맞습니다. 제가 단어 선택이 좀 서툴렀군요...그러나 하지만 제가 생각하기에 static의 뜻이 혼란스럽다고는 생각하지 않습니다. 단지 static의 본질을 생각하지 않고 그 특성에 초점을 맞추게 되면 혼란스러울 뿐이라 생각합니다...
그리고 바인딩은 다소 포괄적인 의미로 사용되는 단어이고 따라서 linkage 대신 바인딩을 사용했다고 해서 크게 잘못되었다고는 생각하지 않습니다...

댓글 달기

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