IT박스

C ++에서 객체 유형 찾기

itboxs 2020. 6. 29. 08:15
반응형

C ++에서 객체 유형 찾기


클래스 A와 클래스 B를 상속받는 다른 클래스가 있습니다 .A 유형의 객체를 매개 변수로 허용하는 함수를 재정의하고 있으므로 A를 수락해야합니다. 그러나 나중에 B 만 가지고있는 함수를 호출합니다. 전달 된 객체가 B 유형이 아닌 경우 false를 반환하고 진행하지 않으려 고합니다.

객체가 함수에 전달한 유형을 찾는 가장 좋은 방법은 무엇입니까?


dynamic_cast가 트릭을 수행해야합니다

TYPE& dynamic_cast<TYPE&> (object);
TYPE* dynamic_cast<TYPE*> (object);

dynamic_cast키워드는 캐스트의 유효성을 보장하기 위해 런타임 검사를 수행, 다른 하나 개의 포인터 또는 참조 유형에서 데이텀을 캐스팅합니다.

실제 객체 유형이 아닌 유형으로 포인터를 캐스트하려고하면 캐스트 결과는 NULL입니다. 실제 객체 유형이 아닌 유형을 참조하기 위해 캐스트하려고하면 캐스트에서 bad_cast예외 발생합니다.

dynamic_cast가 작동하도록 Base 클래스에 하나 이상의 가상 함수가 있는지 확인하십시오.


동적 캐스트는 문제 설명에 가장 적합하지만 다음과 같이 클래스 유형을 찾을 수 있다고 덧붙이고 싶습니다.

#include <typeinfo>

...
string s = typeid(YourClass).name()

이것을 RTTI 라고 부르지 만, 유형을 찾고 특별한 작업을 수행하면 코드가 더 부서지기 때문에 설계를 다시 생각하고 싶을 것입니다.


아마도 개체에 ID "태그"를 포함시키고 클래스 A의 개체와 클래스 B의 개체를 구별하는 데 사용합니다.

그러나 이것은 디자인의 결함을 보여줍니다. 이상적으로 A에없는 B의 메소드는 A의 일부이지만 비워 두어야하고 B가이를 덮어 씁니다. 이것은 클래스 별 코드를 없애고 OOP의 정신에 더 가깝습니다.


완료하기 위해 Robocide를 빌드하고 typeidname ()을 사용하지 않고 단독으로 사용할 수 있음을 지적합니다 .

#include <typeinfo>
#include <iostream>

using namespace std;

class A {
public:
    virtual ~A() = default; // We're not polymorphic unless we
                            // have a virtual function.
};
class B : public A { } ;
class C : public A { } ;

int
main(int argc, char* argv[])
{
    B b;
    A& a = b;

    cout << "a is B: " << boolalpha << (typeid(a) == typeid(B)) << endl;
    cout << "a is C: " << boolalpha << (typeid(a) == typeid(C)) << endl;
    cout << "b is B: " << boolalpha << (typeid(b) == typeid(B)) << endl;
    cout << "b is A: " << boolalpha << (typeid(b) == typeid(A)) << endl;
    cout << "b is C: " << boolalpha << (typeid(b) == typeid(C)) << endl;
}

산출:

a is B: true
a is C: false
b is B: true
b is A: false
b is C: false

당신이 찾고있는 dynamic_cast<B*>(pointer)


당신의 클래스는 다형성이 아니기 때문입니다. 시험:

struct BaseClas { int base; virtual ~BaseClas(){} };
class Derived1 : public BaseClas { int derived1; };

이제 BaseClas다형성입니다. 구조체의 멤버는 기본적으로 공개이기 때문에 클래스를 구조체로 변경했습니다.


다른 사람들이 지적했듯이 dynamic_cast를 사용할 수 있습니다. 그러나 일반적으로 작업중 인 파생 클래스의 유형을 찾기 위해 dynamic_cast를 사용하면 디자인이 잘못되었음을 나타냅니다. A의 포인터를 매개 변수로 사용하는 함수를 재정의하는 경우 클래스 A의 메서드 / 데이터 자체에서 작업 할 수 있어야하며 클래스 B의 데이터에 의존해서는 안됩니다. 경우에 따라 재정의하는 대신 작성하는 메소드가 클래스 B에서만 작동하는지 확인한 다음 클래스 B에 새 메소드를 작성해야합니다.


Your description is a little confusing.

Generally speaking, though some C++ implementations have mechanisms for it, you're not supposed to ask about the type. Instead, you are supposed to do a dynamic_cast on the pointer to A. What this will do is that at runtime, the actual contents of the pointer to A will be checked. If you have a B, you'll get your pointer to B. Otherwise, you'll get an exception or null.


Use overloaded functions. Does not require dynamic_cast or even RTTI support:

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

class Foo {
public:
    void Bar(A& a) {
        // do something
    }
    void Bar(B& b) {
        Bar(static_cast<A&>(b));
        // do B specific stuff
    }
};

If you can access boost library, maybe type_id_with_cvr() function is what you need, which can provide data type without removing const, volatile, & and && modifiers. Here is an simple example in C++11:

#include <iostream>
#include <boost/type_index.hpp>

int a;
int& ff() 
{
    return a;
}

int main() {
    ff() = 10;
    using boost::typeindex::type_id_with_cvr;
    std::cout << type_id_with_cvr<int&>().pretty_name() << std::endl;
    std::cout << type_id_with_cvr<decltype(ff())>().pretty_name() << std::endl;
    std::cout << typeid(ff()).name() << std::endl;
}

Hope this is useful.

참고URL : https://stackoverflow.com/questions/351845/finding-the-type-of-an-object-in-c

반응형