반응형

기반 클래스의 멤버에 접근하는 방법(기반 지식)

  • 기반 클래스의 멤버와 파생클래스의 멤버의 이름이 동일할때는 자신(파생 클래스)의 멤버가 우선

  • 기반 클래스의 멤버에 접근하는 방법

    • d.Base::value

    • static_cast<Base&>(d).value;

  • 값 캐스팅과 참조 캐스팅

    • static_cast<Base>(d): 임시객체 생성. lvalue가 될 수 없음

    • static_cast<Base&>(d): 임시객체를 생성 안함. lvalue가 될 수 있음

#include <iostream>
using namespace std;

struct Base
{
    int value = 10;
};

struct Derived : public Base
{
    int value = 20;
};

int main()
{
    Derived d;

    cout << d.value << endl; // 20
    cout << d.Base::value << endl; // 10

    cout << static_cast<Base>(d).value << endl; // 10 임시객체 생성
    cout << static_cast<Base&>(d).value << endl; // 10 참조

    //static_cast<Base>(d).value = 30; // Error
    static_cast<Base&>(d).value = 30; // OK

}

 

Tuple_element

  •  tuple이 가진 N번째 요소의 타입을 구하는 템플릿

  • 메인 템플릿(Main template) 생성, 구현은 불필요함으로 생략

  • 0번째 요소를 구하는 부분 특수화 구현

  • N번째 요소를 구하는 부분 특수화 구현(Recursive)

#include <iostream>
using namespace std;

// tuple 메인 템플릿
template<typename ... Types> struct xtuple
{
    static constexpr int N = 0;
};

// tuple 부분 특수화
template<typename T, typename ... Types> 
struct xtuple<T, Types...> : public xtuple<Types...> // 타입을 상속을 통해 재귀 저장 효과
{
    T value;
    xtuple() = default; // 기본 생성자
    xtuple(const T& v, const Types& ... args) 
        : value(v), xtuple<Types...>(args...) {} // Pack expansion으로 가변인자 전달

    static constexpr int N = xtuple<Types...>::N + 1;
};

// 메인 템플릿
template<size_t N, typename TP> struct xtuple_element;

// 요소의 타입을 구할 수 있도록 부분 특수화
template<typename T, typename... Types> struct xtuple_element<0, xtuple<T, Types...>>
{
    typedef T type;
    typedef xtuple<T, Types...> tupleType;
};

// 요소의 타입을 구할 수 있도록 부분 특수화
template<size_t N, typename T, typename... Types> 
struct xtuple_element<N, xtuple<T, Types...>>
{
    typedef typename xtuple_element<N-1, xtuple<Types...>>::type type;
    typedef typename xtuple_element<N-1, xtuple<Types...>>::tupleType tupleType;
};

// xtuple 요소를 꺼내는 함수
template<size_t N, typename TP>
typename xtuple_element<N, TP>::type& xget(TP& tp)
{
    return static_cast<typename xtuple_element<N, TP>::tupleType&>(tp).value;
}

int main()
{
    xtuple<int, double, char> t3(1, 3.4, 'A'); // 1
    
    cout << xget<1>(t3) << endl; // 3.4
    xget<1>(t3) = 1.1;
    cout << xget<1>(t3) << endl; // 1.1
}
반응형

반응형
  • Down Casting
    • upcasting된 포인터를 원래의 타입으로 캐스팅 하는것
  • static_cast
    • 컴파일시간 캐스팅
    • 기반 클래스의 포인터가 실제 어떤 타입의 객체를 가리키는지 조사 할 수 없음
  • dynamic_cast
    • 실행시간 캐스팅
    • 잘못된 down casting 사용시 0 반환
    • 가상 함수가 없는 타입은 dynamic_cast를 사용할 수 없음
#include <iostream>
#include <typeinfo>
#include <typeindex>

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

};
class Dog : public Animal 
{
public:
    int color;
};

void foo(Animal* p)
{
    // 선 타입 비교, 후 static_cast
    if (typeid(*p) == typeid(Dog))
    {
        Dog* pDog = static_cast<Dog*>(p);
    }

    //OR

    // 선 dynamic_cast, 후 nullptr 비교
    Dog* pDog = dynamic_cast<Dog*>(p);
    if (pDog == nullptr)
    {
        std::cout << "nullptr" << std::endl;
    }

    std::cout << pDog << std::endl;

}

int main()
{
    Animal a; foo(&a);
    Dog d; foo(&d);
}

RTTI를 사용하지 않고 추가 기능을 제공하는 방법도 생각 필요

#include <iostream>

class Animal 
{
public:
    virtual ~Animal() {}
};
class Dog : public Animal
{
};

void foo(Animal* p)
{
}

void foo(Dog* p)
{
    foo(static_cast<Animal*>(p)); // 기존 공통 함수 기능 지원
    // Dog에 대한 특정 기능은 여기 추가 구현
}

int main()
{
    Animal a; foo(&a);
    Dog d; foo(&d);
}
반응형

+ Recent posts