C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[75088] Re:C++ 고수님께 여쭙니다
빌더(TWx) [builder] 3219 읽음    2018-09-07 16:06
질문 님이 쓰신 글 :
:     
:
: C++ 고수님께 여쭙니다.
:
:
: [myHeader.h]
: class A
: {
: public:
:     static int i;
: };
:
:
: 헤더에 클래스 정적변수가 있고
:
:
: [myClass.cpp]
: #include "myHeader.h"
: int A::i = 7;
:
:
: 클래스 정적변수를 별도의 소스파일에 정의하면 아무런 문제가 없는데요
: 제가 원하는 것은 아래처럼 소스파일 따로 사용하지 않고 헤더파일에만
: 클래스 정적변수를 아래와 같이 정의하려고 하거든요.
:
:
: [myHeader.h]
: class A
: {
: public:
:     static int i;
: };
: int A::i = 7;
:
:
: 그런데 myHeader.h를 한곳에서만 인클루드하면 문제가 없는데
: 다른 소스파일에서 인클루드하면 int A::i 가 중복정의 되어있다는
: 에러와 함께 컴파일 실패합니다. ㅠㅠ
:
: 별도의 소스파일 안쓰고 헤더파일 하나로 클래스 정적변수를 같이
: 정의해서 사용하는 방법이 없을까요. ㅠㅠ




답변:


헤더파일에 클래스 static 멤버 변수가 정의되어 있는 상태에서 헤더파일이 여러 소스파일 들에서 include 되면
컴파일된 오브젝트 파일들에 같은 심볼이 생성되어... 링크 시에 duplicated 심볼 에러가 발생하죠.

클래스 static 멤버 변수를 별개의 소스파일에서 정의하는 방법은 legacy 컴파일러에서 사용하는 방법이고.


별개의 소스파일 사용하지 않고 헤더파일 안에서만 정의하는 방법은
3가지 경우로 나누어서 볼 수 있는데...


1.

컴파일러가 Implicit로 해당 심볼을 오브젝트 파일에 COMDAT attribute 속성을 갖도록 생성하는 기능이 있으면
오브젝트 파일 들에서 COMDAT attribute 속성을 갖고있는 같은 심볼들에 대해서...
링커가 하나의 인스턴스만 선택하고 나머지는 discard 해서 duplicated 심볼 링크 에러가 발생하지 않게 하는 경우가 있을 수 있고.


2.

<Header.h>
class A
{
public:
    static int i;
};
int __declspec(selectany) A::i = 7;

위와 같이 __declspec(selectany) 랭귀지 익스텐션 키워드를 명시적으로 지정해 주면
컴파일러가 Header.h 를 include 하는 소스 파일들을 컴파일해서 오브젝트 파일을 생성할 때
해당 심볼을 COMDAT attribute 속성으로 생성하게 해서.. 링커가 duplicated 심볼들을 discard 하고
하나의 인스턴스만 사용해서 링크하도록 해서 duplicated 심볼 링크 에러가 발생하지 않게 하는 경우도 있을 수 있는데.

__declspec(selectany)를 명시적으로 지정해서 사용하는 방법은...
C++ COM 을 다룰 때 GUID를 선언과 정의를 동시에 같이 처리하도록 헤더파일을 만들 때
많이 쓰이는 테크닉이기도 함.



3.

그러나... 컴파일러가 C++17을 지원하면 간단하게 아래와 같이 정의 할 수 있지요.

<Header.h>
class A
{
public:
    static inline int i = 7; // inline 키워드 사용. 선언과 정의를 동시에.
};


VC++2017  C++ Language Standard 옵션에서 C++17로 지정해서 컴파일 하면 됨.

엠바에서 포팅해서 베포하고 있는 clang C++ 컴파일러는 오래전에 나온 v3.3 버전을
포팅해 놓은 거라 C++17 지원하지 않음.

현재 clang C++ 컴파일러 head는 8.0 임.



+ -

관련 글 리스트
75086 C++ 고수님께 여쭙니다 질문 3005 2018/09/07
75088     Re:C++ 고수님께 여쭙니다 빌더(TWx) 3219 2018/09/07
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.