2013-10-18 2 views
0

나는 추상적 인 기본 클래스와 템플릿 파생 클래스를 가지고있다. 파생 된 객체는 파생 된 객체의 이전 인스턴스와 정수로 구성 될 수 있습니다. 지금까지 우리는 C++ : 어떻게 static_cast를 피할 수 있습니까?

struct base { 
    /* ...pure virtual functions here... */ 

    virtual ~base() = default; 
    /* NO DATA */ 
}; 

template <class D> 
struct derived : base { 
    derived() = default; 

    derived(int x, const derived& previous) { 
    /* to construct I need access to previous.data_ */ 
    } 

    /* ...overriden virtual functions here... */ 

    ~derived() = default; 

    D data_; 
}; 

는 파생 클래스의 생성자가 previous 파생 된 개체의 data_ 멤버에 액세스 할 수 있어야한다는 사실을 명심해야합니다. 이제 derived<D> 유형의 객체를 생성하는 함수를 만들고 정수 및 이전 인스턴스 인 derived<D>을 입력하고 base에 대한 포인터를 반환합니다. 문제는 사용자가 base 클래스 포인터로 작업되기 때문에, 함수가 다음과 같이해야한다는 것입니다 :

template <class D> 
std::shared_ptr<base> getNext(int x, std::shared_ptr<base> current) { 
    return std::make_shared<derived<D>>(x, *current); /* ERROR */ 
} 

이를, 독자가 추측 한 것처럼 알려진 변환이 없다는 것을 말하는 컴파일 오류를 생성 base에서 derived<D>까지 내가 사용할 수있는 한 가지는 기본 객체의 유형이 항상 derived<D>이 될 것이므로 static_cast<derived<D>&>(*current)이지만 가능한 경우 모든 캐스트를 피하고 싶습니다. 모든 아이디어가이 문제를 극복하는 방법>? 미리 감사드립니다!

+0

왜 복사 생성자를 사용하지 않으시겠습니까? –

+0

@John Smith : 파생 생성자는 단순히 이전 객체를 복사하는 것이 아닙니다. 그것은 이전 객체에서 발견 된 데이터를 사용하여 자체 객체를 생성하기위한 것입니다. – linuxfever

+0

@HeywoodFloyd : 나는 그것이 중요 할 것이라고 생각하지 않는다.문제점은 리턴 유형이 아닌 getNext의 입력 매개 변수에 의해 작성됩니다. – linuxfever

답변

0

을 다형성 클래스를 사용하고 파생 된 유형으로 캐스트해야하는 경우가 종종 있습니다. 이것은 디자인에 문제가 있다는 것을 나타내는 단서가됩니다. 결국 파생 클래스에 도달해야하는 경우 virtual 함수가있는 이유는 무엇입니까? 나는 이것에 예외가 없다는 것을 말하지 않고있다 - 그러나 나는 그것들이 아주 적다는 것을 말할 것이다.

이 경우 개체를 복제하기 위해 캐스팅해야한다고 생각합니다. 대신 기본 클래스 (여기서는 getNext)에 clone 메서드를 제공합니다. 그 virtual을 확인합니다 파생 클래스에서 재정의하고, 그 대신 전화 :

struct base { 
public: 
    virtual std::shared_ptr<base> getNext(int x) = 0; 
}; 

template <typename D> 
struct derived : public base 
{ 
public: 
    std::shared_ptr<base> getNext(int x) 
    { 
    std::shared_ptr <derived> clone = std::make_shared <derived<d>> (x, *this); 
    return std::static_pointer_cast <base> (clone); 
    } 
}; 
+0

대단히 고마워, 나는 너의 대답을 받아 들였다. – linuxfever

+0

@linuxfever : 행운을 빌어 요. –

0

어쨌든 static_cast을 사용하고 싶지 않습니다. dynamic_pointer_cast을 사용하고 결과를 파생 유형으로 캐스트 할 수 있는지 확인하십시오.

사용자 인터페이스는 당신이 당신의 Data 객체를 입력하는 데 필요한 모든 정보가있는 경우, 당신은 당신이 캐스트 일을 방지 할 수 있도록 변환 생성자를 만들 수 있습니다 : 당신이 함께 작업 할 때

template<typename T> 
class MyDerived : public Base 
{ 
public: 
    // other functions 
    MyDerived(std::shared_ptr<Base> p) 
    { 
     // initialize _data 
    } 

private: 
    Data _data; 
}; 
1

을 당신은 파생 클래스가 어떤 유형 알려주는 기본 클래스에 가상 접근-기능을 사용할 수 있습니다. 그런 다음 static cast을 안전하게 사용하여 기본 클래스를 캐스팅 할 수 있습니다. 만을 알고 에 파생 된 유형을 필요로하는 경우

Dog A; 
Cat B; 

Animal *unknown_animal = &A; 

if (unknown_animal->isDog()) { 
    Dog *dog = static_cast<Dog*>(unknown_animal); 
} 
else if (unknown_animal->isCat()) { 
    Cat *cat = static_cast<Cat*>(unknown_animal); 
} 

액세서 기능도 유용하지만, 할 필요가 없습니다 :

class Animal { 
    virtual bool isDog() { return false; } 
    virtual bool isCat() { return false; } 
}; 

class Dog : public Animal { 
    virtual bool isDog() { return true; } 
}; 

class Cat : public Animal { 
    virtual bool isCat() { return true; } 
}; 

나는 다음과 같이 안전하게 기본 클래스를 캐스팅 할 수 있습니다 그것을에 접속하십시오.