无法动态转换为ptr

时间:2015-10-19 19:04:24

标签: c++ templates

我正在尝试实现类似于boost :: any的非常基本的类,但是我遇到了一个问题,我无法绕过它。问题是使用dynamic_cast将指针转换为另一个,错误说明:

cannot dynamic_cast 'input.Any::m_targetPtr' (of type 'class Any::StorageInterface*') to type 'int*' (target is not pointer or reference to class)

课程来源如下:

class Any{
public:
    template <typename T>
    Any(T input): m_targetPtr(new StorageImpl<T>(input)){}
    ~Any(){delete m_targetPtr;}

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

    template<typename T>
    T* cast(Any& input){
        return dynamic_cast<T*>(input.m_targetPtr); //here comes the trouble
    }

    template <typename T>
    class StorageImpl : public StorageInterface{
    public:
        StorageImpl(T& input): m_target(&input){}
        T* m_target;
    };

    StorageInterface* m_targetPtr;
};

这就是我想要执行的方式:

int i=150;
Any asdf(i);
cout<< (asdf.cast<int>(asdf)) << endl;

所以我的理解是。我有一个int变量,而cast模板我将指针传递给此int,模板中的T为int,因此在强制转换源中我们有int作为推导参数int*作为返回值,我使用dynamic_cast<int*>类型的参数m_target执行StorageInterface*。为什么然后我收到错误,我的目标不是指针?

3 个答案:

答案 0 :(得分:2)

我在以下代码中看到以下问题。

template<typename T>
T* cast(Any input){
    return dynamic_cast<T*>(input.m_targetPtr); //here comes the trouble
}
  1. 您需要投放到StorageImpl<T>*,而不是T*

  2. StorageImpl未公开其成员m_target

  3. 公开m_target成员,使其成为public或提供一个返回值的函数。

    cast功能更改为:

    template<typename T>
    T* cast(Any input){
        return dynamic_cast<StorageImpl<T>*>(input.m_targetPtr)->m_target;
    }
    

    建议改进:

    input中不需要cast参数。它可以是:

    template<typename T>
    T* cast(){
        return dynamic_cast<StorageImpl<T>*>(m_targetPtr)->m_target;
    }
    

    然后,您的通话也可以简化为:

    cout<< (asdf.cast<int>()) << endl;
                      //  ^^^ No need to use asdf again in the call.
    

    进一步改进的建议

    发布的代码中的StorageImpl存储指向容易变为无效的对象的指针。我建议改为存储一个对象。然后,Any::cast()可以返回引用而不是指针。

    class Any {
       public:
          template <typename T>
             Any(T input): m_targetPtr(new StorageImpl<T>(input)){}
          ~Any(){delete m_targetPtr;}
    
          class StorageInterface {
             public:
                virtual ~StorageInterface(){}
          };
    
          template<typename T>
             T const& cast() const {
                return dynamic_cast<StorageImpl<T>*>(m_targetPtr)->m_target;
             }
    
          template<typename T>
             T& cast() {
                return dynamic_cast<StorageImpl<T>*>(m_targetPtr)->m_target;
             }
    
          template <typename T>
             class StorageImpl : public StorageInterface {
                public:
                   StorageImpl(T const& input): m_target(input){}
                   T m_target;
             };
    
          StorageInterface* m_targetPtr;
    };
    

答案 1 :(得分:1)

问题在于dynamic_cast<T>(X)如果T与[{1}}属于同一类层次结构,则无法将类型X转换为X类型。动态强制转换用于多态,用于向下转换TAnimal*,例如,Dog*继承自class Dogclass Animal包含虚函数。问题是class Animal不是类类型,因此int可以提前得出结论dynamic_castint不要共享类层次。

错误消息并不是说您的目标不是指针,而是说您的目标不是指向类对象的指针(并且也不是对类对象的引用)。< / p>

R Sahu明确指出你要转向StorageInterface,这更有意义。

答案 2 :(得分:1)

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCellWithReuseIdentifier(ACDFilterCollectionViewCellConstants.CellIdentifier, forIndexPath: indexPath) as! ACDFilterCollectionViewCell let filterType = filters[indexPath.row] cell.titleLabel.text = filterType.rawValue let skview = SKView(frame: cell.frame) cell.filterView.addSubview(skview) return cell } 旨在用于将指向多态结构的指针转换为同一层次结构中的另一个多态结构。多态结构是具有至少一个虚函数或虚继承的结构。显然,int *不是结构体,也不是多态的。

你可能打算改为演员:

dynamic_cast<T>

为什么要将对象的副本发送给自己?我不太容易将函数限制为实例本身:

template<typename T>
T* cast(Any input){
    return dynamic_cast<StorageImpl<T>*>(input.m_targetPtr)->m_target; // better?
}

您现在可以这样使用它:

template<typename T>    
T* cast(){
    return dynamic_cast<StorageImpl<T>*>(m_targetPtr)->m_target; // even better
}

最后,为了使您的代码更清晰,更不容易出错,最后还是可以完成。您是否看到了潜在的未定义行为?您的代码中有双重删除:

asdf.cast<int>();

在构造函数中,您保存临时的地址:

template<typename T>
T* cast(Any input){
    return dynamic_cast<T*>(input.m_targetPtr); //here comes the trouble
    // input is deleted here, so asdf will have a dangling pointer and double delete the m_targetPtr!
}

按值传递(和移动)可以解决这个问题。

使用此类的任何代码都会受到这些错误的影响。使用// input is a reference to a variable from the 'Any' class constructor, it will be deleted StorageImpl(T& input): m_target(&input){} 和值语义可以解决这个问题:

std::unique_ptr

此代码将要求T可移动。