C++에서 typeid

wafe의 이미지

typeid는 포인터에 대해서는 쓸 수 없나요?

class CurvedEdge : public Edge
{
...
};


Edge* pEdge = new CurvedEdge(...);
assert(typeid(pEdge) == typeid(CurvedEdge*));

이렇게 해보니 항상 assertion fail 이네요.

Visual C++ 6.0 환경입니다.

Fe.head의 이미지

*pEdge 이렇게 한번 해보세요..

assert(typeid(*pEdge) == typeid(CurvedEdge));

g++에서는 되는군요..

고작 블로킹 하나, 고작 25점 중에 1점, 고작 부활동
"만약 그 순간이 온다면 그때가 네가 배구에 빠지는 순간이야"

wafe의 이미지

음... 참조형으로 고쳐서 해봐도 안되고 fehead님 말씀대로 해봐도 안되는군요. VC++이 이 기능을 제대로 지원하지 못하나봐요. 결국에는 그냥 dynamic_cast를 이용해서 해결하기는 했는데 한참 삽질했네요.

Heejoon Lee

mr.lee의 이미지

dynamic_cast<> 의 bad_cast exception을 이용해서 type 매칭검사를 하셨나 보네요.

VC++ 에서는 RTTI 를 위해서 /GR 컴파일옵션을 활성화하여야 하며 /GR- 가 디폴트입니다. 프로젝트 등록정보에서 컴파일옵션으로 /GR을 추가하여 주시고, base class에는 최소한 하나의 virtual class가 있어야 하므로, 다음과 같이 해주시면 됩니다.

#include <iostream>

class Edge {
	virtual void prn() {}
};

class CurvedEdge : public Edge {};

int main() {
	Edge* pEdge = new CurvedEdge();
	assert(typeid(pEdge) == typeid(Edge*));
	assert(typeid(*pEdge) == typeid(CurvedEdge));
	std::cout << typeid(pEdge).name() << std::endl;
	std::cout << typeid(*pEdge).name() << std::endl;
	return 0;
}

결과

class Edge *
class CurvedEdge
wafe의 이미지

아하 base class에 가상 함수가 하나도 없어서 그랬군요. 고맙습니다. ^^

지금은 dynamic_cast에서 캐스팅이 제대로 되지 않을 경우 NULL 포인터를 리턴한다는 사실을 가지고 타입을 판별하고 있는데 이것과 typeid를 쓰는 방법 둘 중에 더 권장할 만한 방법은 어느걸까요?

음... 그리고 dynamic_cast와 typeid가 타입을 판별하는 방식이 서로 다른 모양이네요. base class에 가상 함수가 있고 없고에 따라 다른 걸 보면 typeid는 virtaul function table을 쓰는건가요?

Heejoon Lee

jeongkyu의 이미지

올려주신 코드에서 assert가 fail 하는 것이 맞는 것 같습니다.

뉴스그룹에 typeid 와 dynamic_cast 의 속도에 대한 토론이 있는데, 중간에 두 연산자의 차이점에 대해서 잘 설명을 해 놓았습니다. 구글 뉴스그룹에서 "Performance: typeid() vs dynamic_cast" 를 검색하시면 나올겁니다. (URL이 붙여 넣기에 좀 길군요 ;-) )

Quote:
If you use typeid, you are comparing two exact types. OTOH, dynamic_cast has to check for classes in the whole hierarchy (if required) and adjust the pointer so that it points the proper sub-object within the original pointer. (The latter comes into picture for multiple inheritance, usually.

vc++ 메뉴얼에 typeid 연산자는 const type_info& 를 반환 한다고 되어 있어서 디버거에서 결과값을 확인해보니, 각각 부모 클래스와 자식 클래스의 타입 정보를 가지고 있습니다.

const type_info& a = typeid(pEdge);
const type_info& b = typeid(CurvedEdge*)
assert (a != b);

내친김에 (정말 오랫만에) C++에 관한 명저 "C++ FAQs (2nd Ed)" 까지 뒤져보았는데, 역시나 간결하면서도 심도있게 설명하고 있네요. 기회되면 한번 읽어보셔도 좋을 것 같습니다.

Jeongkyu Kim
OpenOffice.org Korean community lead

Official website http://ko.openoffice.org
Community forum http://oooko.net/
Personal blog http://oooko.net/gomme

doldori의 이미지

wafe wrote:
아하 base class에 가상 함수가 하나도 없어서 그랬군요.

위에서 dynamic_cast를 썼다고 하시길래 다형적인(기초 클래스에 가상함수가 있는)
클래스라고 생각했는데 그게 아니었습니까? 다형적이 아닌 클래스에서
dynamic_cast를 쓰면 컴파일 에러가 날 텐데요. :shock:

wafe wrote:
지금은 dynamic_cast에서 캐스팅이 제대로 되지 않을 경우 NULL 포인터를 리턴한다는 사실을 가지고 타입을 판별하고 있는데 이것과 typeid를 쓰는 방법 둘 중에 더 권장할 만한 방법은 어느걸까요?

dynamic_cast가 유연성이나 확장성에서 더 유리하므로 일반적으로는 이것을
많이 씁니다. typeid는 "정확한" 타입을 알아야 할 때 쓰고요.
struct S
{
    virtual ~S();
};

struct T : public S { };

T t;
assert(dynamic_cast<S*>(&t));
assert(typeid(S*) != typeid(&t));

wafe wrote:
음... 그리고 dynamic_cast와 typeid가 타입을 판별하는 방식이 서로 다른 모양이네요. base class에 가상 함수가 있고 없고에 따라 다른 걸 보면 typeid는 virtaul function table을 쓰는건가요?

아니오. typeid는 클래스형뿐만 아니라 내장형에서도 동작합니다.
wafe의 이미지

doldori wrote:
위에서 dynamic_cast를 썼다고 하시길래 다형적인(기초 클래스에 가상함수가 있는)
클래스라고 생각했는데 그게 아니었습니까? 다형적이 아닌 클래스에서
dynamic_cast를 쓰면 컴파일 에러가 날 텐데요. :shock:

실제로 프로젝트에서 사용하는 코드는 다형적인 클래스인데, typeid가 제대로 동작하는지 테스트 해보려고 간단히 짠 코드에서는 그렇지 않았거든요. 가상 함수가 있고 없고에 별 차이가 있겠냐고 생각했기 때문에...

사실 "다형적"이라는 게 무슨 말인지 아직까지 몰랐어요. :oops:

테스트 코드를 짤 때도 뭣좀 알고 짜야겠네요. ㅜ.ㅜ

Heejoon Lee

댓글 달기

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