문제

나는 사용 라인을 따라 생각하고 있었다 typeid() 그러나 나는 그 유형이 다른 클래스의 서브 클래스인지 묻는 방법을 모른다 (그건 그렇고, 추상적).

도움이 되었습니까?

해결책

당신은 정말로 안됩니다. 프로그램이 객체의 클래스가 무엇인지 알아야하는 경우 일반적으로 설계 결함을 나타냅니다. 가상 함수를 사용하여 원하는 동작을 얻을 수 있는지 확인하십시오. 또한, 당신이하려는 일에 대한 자세한 정보는 도움이 될 것입니다.

나는 당신이 다음과 같은 상황이 있다고 가정합니다.

class Base;
class A : public Base {...};
class B : public Base {...};

void foo(Base *p)
{
  if(/* p is A */) /* do X */
  else /* do Y */
}

이것이 당신이 가진 것이라면 다음과 같은 일을 시도하십시오.

class Base
{
  virtual void bar() = 0;
};

class A : public Base
{
  void bar() {/* do X */}
};

class B : public Base
{
  void bar() {/* do Y */}
};

void foo(Base *p)
{
  p->bar();
}

편집하다: 이 답변에 대한 논쟁은 몇 년이 지난 후에도 여전히 진행되기 때문에 몇 가지 언급을 던져야한다고 생각했습니다. 기본 클래스에 대한 포인터 또는 참조가 있고 코드가 파생 된 클래스의 객체를 알아야하는 경우 위반합니다. Liskov 대체 원리. 밥 삼촌 이것을 "호출"객체 지향 디자인에 대한 anathema".

다른 팁

 

class Base
{
  public: virtual ~Base() {}
};

class D1: public Base {};

class D2: public Base {};

int main(int argc,char* argv[]);
{
  D1   d1;
  D2   d2;

  Base*  x = (argc > 2)?&d1:&d2;

  if (dynamic_cast<D2*>(x) == nullptr)
  {
    std::cout << "NOT A D2" << std::endl;
  }
  if (dynamic_cast<D1*>(x) == nullptr)
  {
    std::cout << "NOT A D1" << std::endl;
  }
}

당신은 그것을 할 수 있습니다 dynamic_cast (적어도 다형성 유형의 경우).

실제로, 두 번째 생각에-당신은 그것이 특별히 특정 유형인지 알 수 없습니다. dynamic_cast-하지만 그 유형인지 하위 클래스인지 알 수 있습니다.

template <class DstType, class SrcType>
bool IsType(const SrcType* src)
{
  return dynamic_cast<const DstType*>(src) != nullptr;
}

dynamic_cast 유형에 상속 계층 구조의 어느 곳에서나 대상 유형이 포함되어 있는지 확인할 수 있습니다 (예, B 상속 A 그리고 C, 그것은 돌릴 수 있습니다 A* 직접 a C*). typeid() 객체의 정확한 유형을 결정할 수 있습니다. 그러나 이것들은 둘 다 매우 드물게 사용해야합니다. 이미 언급 된 바와 같이, 디자인 결함을 나타 내기 때문에 항상 동적 유형 식별을 피해야합니다. (또한 객체가 대상 유형을 확실히 알고 있다면 static_cast. 부스트 제공 a polymorphic_downcast 그것은 다운 캐스트를 할 것입니다 dynamic_cast 그리고 assert 디버그 모드에서 릴리스 모드에서는 static_cast).

C ++에서 객체의 유형을 확인하고 싶지 않아야한다고 동의하지 않습니다. 당신이 그것을 피할 수 있다면, 나는 당신이해야한다는 데 동의합니다. 어떤 상황에서도 그렇게하지 말아야한다고 말하는 것은 너무 멀리 가고 있습니다. 당신은 많은 언어로 이것을 할 수 있으며, 그것은 당신의 삶을 훨씬 쉽게 만들 수 있습니다. 예를 들어 Howard Pinsley는 C#에 대한 그의 게시물에서 어떻게 우리에게 어떻게 우리에게 보여주었습니다.

QT 프레임 워크와 많은 작업을 수행합니다. 일반적으로, 나는 그들이하는 일을 마치고 (적어도 프레임 워크에서 일할 때) 내가하는 일을 모델링합니다. Qobject 클래스는 모든 QT 객체의 기본 클래스입니다. 해당 클래스에는 ISWIDGETTYPE () 및 ISWINDOWTYPE () 기능이 빠른 서브 클래스 점검으로 있습니다. 그렇다면 왜 자신의 파생 수업을 확인할 수 없습니까? 다음은 이러한 다른 게시물의 Qobject 스핀 오프입니다.

class MyQObject : public QObject
{
public:
    MyQObject( QObject *parent = 0 ) : QObject( parent ){}
    ~MyQObject(){}

    static bool isThisType( const QObject *qObj )
    { return ( dynamic_cast<const MyQObject*>(qObj) != NULL ); }
};

그런 다음 Qobject로 포인터를 전달할 때 정적 멤버 기능을 호출하여 파생 클래스를 가리키는 지 확인할 수 있습니다.

if( MyQObject::isThisType( qObjPtr ) ) qDebug() << "This is a MyQObject!";

나는 당신의 문제를 올바르게 이해하는지 모르겠으므로 내 말로 다시 말해 드리겠습니다 ...

문제 : 수업이 주어졌습니다 B 그리고 D, D 서브 클래스입니다 B (혹은 그 반대로도?)

해결책 : 일부 템플릿 매직을 사용하십시오! 좋아, 진지하게, 당신은 전설적인 C ++ 작가 Andrei Alexandrescu가 제작 한 훌륭한 템플릿 메타 프로그래밍 라이브러리 인 Loki를 살펴 봐야합니다.

보다 구체적으로 다운로드 로키 헤더를 포함합니다 TypeManip.h 소스 코드에서 그것으로부터 다음을 사용하십시오 SuperSubclass 다음과 같이 클래스 템플릿 :

if(SuperSubClass<B,D>::value)
{
...
}

문서에 따르면 SuperSubClass<B,D>::value 만약 그렇다면 사실이 될 것입니다 B 공공 기반입니다 D, 또는 만약 B 그리고 D 동일한 유형의 별칭입니다.

D 서브 클래스입니다 B 또는 D 와 같다 B.

이게 도움이 되길 바란다.

편집하다:

평가에 주목하십시오 SuperSubClass<B,D>::value 사용하는 일부 방법과 달리 컴파일 시간에 발생합니다 dynamic_cast, 따라서 런타임 에이 시스템을 사용하는 것에 대한 페널티는 없습니다.

#include <stdio.h>
#include <iostream.h>

class Base
{
  public: virtual ~Base() {}

  template<typename T>
  bool isA() {
    return (dynamic_cast<T*>(this) != NULL);
  }
};

class D1: public Base {};
class D2: public Base {};
class D22: public D2 {};

int main(int argc,char* argv[]);
{
  D1*   d1  = new D1();
  D2*   d2  = new D2();
  D22*  d22 = new D22();

  Base*  x = d22;

  if( x->isA<D22>() )
  {
    std::cout << "IS A D22" << std::endl;
  }
  if( x->isA<D2>() )
  {
    std::cout << "IS A D2" << std::endl;
  }
  if( x->isA<D1>() )
  {
    std::cout << "IS A D1" << std::endl;
  }
  if(x->isA<Base>() )
  {
    std::cout << "IS A Base" << std::endl;
  }
}

결과:

IS A D22
IS A D2
IS A Base

RTTI를 사용하지 않는 한 템플릿을 사용하여 컴파일 시간에만 수행 할 수 있습니다.

유형에 대한 정보가 포함 된 type_info 구조에 대한 포인터를 산출하는 typeid 함수를 사용할 수 있습니다.

그것에서 읽으십시오 위키 백과

C#에서는 간단히 말할 수 있습니다.

if (myObj is Car) {

}

나는 사용 라인을 따라 생각하고 있었다 typeid()...

그렇습니다. 비교하여 수행 할 수 있습니다. typeid().name(). 이미 설명 된 상황을 취하면 다음과 같습니다.

class Base;
class A : public Base {...};
class B : public Base {...};

void foo(Base *p)
{
  if(/* p is A */) /* do X */
  else /* do Y */
}

가능한 구현 foo(Base *p) 다음과 같습니다.

#include <typeinfo>

void foo(Base *p)
{
    if(typeid(*p) == typeid(A))
    {
        // the pointer is pointing to the derived class A
    }  
    else if (typeid(*p).name() == typeid(B).name()) 
    {
        // the pointer is pointing to the derived class B
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top