문제

사용 sizeof 연산자, 모든 유형의 크기를 결정할 수 있지만 런타임에 다형성 클래스의 크기를 어떻게 동적으로 결정할 수 있습니까?

예를 들어, 나는에 대한 포인터가 있습니다 Animal, 그리고 나는 그것이 가리키는 실제 객체의 크기를 얻고 싶습니다. Cat 또는 a Dog. 가상 메소드를 만드는 것이 부족한 간단한 방법이 있습니까? Animal::size 그리고 그것을 반환하기 위해 그것을 과부하 시키십시오 sizeof 각 특정 유형의?

도움이 되었습니까?

해결책

가능한 유형 세트를 알고 있다면 RTTI를 사용하여 수행하여 동적 유형을 찾을 수 있습니다. dynamic_cast. 그렇지 않으면 유일한 방법은 가상 기능을 사용하는 것입니다.

다른 팁

또는 dynamic_cast보다 빠를 수있는 TypeId를 사용할 수 있습니다 (Dynamic_cast를 사용하면 계층 구조에서 중개자 유형으로 캐스트 할 수 있음).

다소 나쁘게 보입니다.

#include <iostream>
#include <typeinfo>

class Creature
{
    char x[4];
public:
    virtual ~Creature() {}
};

class Animal: public Creature { char x[8];};

class Bird: public Creature { char x[16]; };

class Dog: public Animal { char x[32]; };

class Cat: public Animal { char x[64]; };

class Parrot: public Bird { char x[128]; };

unsigned creature_size(const Creature& cr)
{
    if (typeid(cr) == typeid(Animal)) {
        return sizeof (Animal);
    }
    else if (typeid(cr) == typeid(Dog)) {
        return sizeof(Dog);
    }
    else if (typeid(cr) == typeid(Cat)) {
        return sizeof(Cat);
    }
    else if (typeid(cr) == typeid(Bird)) {
        return sizeof(Bird);
    }
    else if (typeid(cr) == typeid(Parrot)) {
        return sizeof(Parrot);
    }
    else if (typeid(cr) == typeid(Creature)){
        return sizeof(Creature);
    }
    assert(false && "creature_size not implemented for this type");
    return 0;
}

int main()
{
    std::cout << creature_size(Creature()) << '\n'
    << creature_size(Animal()) << '\n'
    << creature_size(Bird()) << '\n'
    << creature_size(Dog()) << '\n'
    << creature_size(Cat()) << '\n'
    << creature_size(Parrot()) << '\n' ;
}

각각의 새로운 유형마다 creature_size 함수에 코드를 추가해야합니다. 가상 크기 기능을 사용하면 각 클래스 에서도이 기능을 구현해야합니다. 그러나이 기능은 상당히 단순해질 것입니다 (완벽하게 Copy-N Pastable, 이는 언어의 한계와 코드 설계 문제가있을 수 있음을 보여줍니다).

virtual unsigned size() const { return sizeof(*this); }

기본 클래스에서 추상화 할 수 있습니다. 즉,이 메소드를 무시하는 것을 잊어 버린 경우 컴파일러 오류가 될 수 있습니다.

편집 : 이것은 자연스럽게 그 크기를 알고 싶은 생물을 주어야한다고 가정합니다. 개를 다루고 있다고 믿을만한 강한 이유가 있다면 - 개의 서브 클래스 (그리고 서브 클래스인지 상관하지 않음) 자연스럽게 Dynamic_cast를 사용할 수 있습니다. 애드 혹 테스트.

소스 클래스의 디자인을 변경할 수 있다면 동적 다형성 (가상 함수를 사용하는)을 정적 다형성으로 완전히 대체하고 CRTP 관용구:

template <class TDerived>
class Base
{
public:
    int getSize()
    { return sizeof(TDerived); }

    void print()
    {
          std::cout
             << static_cast<TDerived*>(this)->getSize()
             << std::endl;
    }

    int some_data;
};

class Derived : public Base<Derived>
{
public:
    int some_other_data1;
    int some_other_data2;
};

class AnotherDerived : public Base<AnotherDerived>
{
public:
    int getSize()
    { return some_unusual_calculations(); }
    // Note that the static_cast above is required for this override to work,
    //  because we are not using virtual functions
};

int main()
{
    Derived d;
    d.print();

    AnotherDerived ad;
    ad.print();

    return 0;
}

필요할 때이를 수행 할 수 있습니다 다형성 행동 프로그램의 프로그램을 컴파일 타임으로 결정할 수 있습니다 (예 : sizeof CASE), CRTP는 런타임에 원하는 대상을 해결하기 위해 동적 다형성의 유연성이 없기 때문에.

정적 다형성은 또한 가상 기능 통신 오버 헤드를 제거함으로써 더 높은 성능의 이점을 가지고 있습니다.

기본 클래스를 템플릿으로 템플릿을 만들고 싶지 않거나 동일한 위치 (배열 또는 벡터와 같은)에서 다른 파생 된 기본 클래스 인스턴스를 보유 해야하는 경우 중산층에서 CRTP를 사용하여 다형성 동작을 해당 클래스로 이동할 수 있습니다. (와 유사합니다 다형성 사본 구성 예 위키 백과에서) :

class Base
{
public:
    virtual int getSize() = 0;

    void print()
    {
        std::cout << getSize() << std:endl;
    }

    int some_data;
};

template <class TDerived>
class BaseCRTP: public Base
{
public:
    virtual int getSize()
    { return sizeof(TDerived); }
};

class Derived : public BaseCRTP<Derived>
{
    // As before ...
};

class AnotherDerived : public BaseCRTP<AnotherDerived>
{
    // As before ...

    // Note that although no static_cast is used in print(),
    //  the getSize() override still works due to virtual function.
};

Base* obj_list1[100];
obj_list1[0] = new Derived();
obj_list1[2] = new AnotherDerived();

std::vector<Base*> obj_list2;
obj_list2.push_back(new Derived());
obj_list2.push_back(new AnotherDerived());

--
업데이트: 나는 이제 비슷하지만 더 상세한 것을 발견했습니다 대답 Stackoverflow에서 위의 파생 클래스에서 더 파생된다면 (예 : class FurtherDerived : public Derived {...}), sizeof 올바르게보고하지 않습니다. 그는 a 더 복잡한 변형 이것을 극복하기위한 코드의.

나는 누군가가 적절한 특성을 구현하는 대신 발명 된 type_id ()를 믿을 수 없다 ....

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top