将基类实例向下转型为空子接口

问题描述 投票:0回答:1

我想知道将基子类向下转换为空接口子类的有效性。请参阅下面的示例。基本上我想以通用模板自由方式存储数据(从可以是任何简单算术类型的文件中读取数据。在下面的示例中

std::is_arthmetic<T>
应该始终为真)。

#include <iostream>
#include <vector>

/**
 * Mother class holding data.
 */
class NonTypedData
{
    std::vector<uint8_t> data_;

    public:

    NonTypedData(std::size_t size) : data_(size) {}

    std::size_t size() const { return data_.size(); }

    const uint8_t* get() const { return data_.data(); }
          uint8_t* get()       { return data_.data(); }
};

/**
 * Empty child interface class that handles typed access
 */
template <typename T>
struct TypedData : public NonTypedData
{
    static_assert(std::is_arithmetic<T>::value, "TypedData not supported for non arithmetic types.");

    const T* get() const { return reinterpret_cast<const T*>(this->NonTypedData::get()); }
          T* get()       { return reinterpret_cast<      T*>(this->NonTypedData::get()); }
    std::size_t size() const { return this->NonTypedData::size() / sizeof(T); }
};

template <typename T>
void fill(TypedData<T>& data)
{
    for(std::size_t i = 0; i < data.size(); i++) {
        data.get()[i] = i;
    }
}

template <typename T>
void print(const TypedData<T>& data)
{
    for(std::size_t i = 0; i < data.size(); i++) {
        std::cout << ' ' << data.get()[i];
    }
    std::cout << std::endl;
}

int main()
{
    NonTypedData data(10*sizeof(int));

    fill(static_cast<TypedData<int>&>(data));
    print(static_cast<const TypedData<int>&>(data));

    return 0;
}


我强烈觉得这是未定义的行为,但我不确定。是吗?

另一方面,我发现这个构造之王非常有用,我觉得可能有一种方法可以在不进入 UB 土地的情况下完成类似的事情。你怎么认为?也许是对

NonTypedData
实例中的
TypedData
实例的引用?

c++ undefined-behavior downcast
1个回答
0
投票
std::vector<uint8_t> data_;
uint8_t* get()       { return data_.data(); }
T* get()       { return reinterpret_cast<      T*>(this->NonTypedData::get()); }
data.get()[i] = i;

data.get()[..]
使用指向
uint8_t
的指针取消引用存储在向量中的
int
数据。这是未定义的行为 -
int
数组内没有
uint8_t
。有
uint8_t
值,您可以使用指向
uint8_t
的指针来取消引用它,而不是任何其他类型。

你觉得怎么样?

无效。

如果您想要从

int
得到
uint8_t
,请使用位移位和数学运算。作为最后的手段,如果您想将存储在
uint8_t
数组中的位模式解释为
int
,请使用
memcpy
std::bit_cast
(可以实现
memcpy
)。

可能是 TypedData 实例中对 NonTypedData 实例的引用?

没有。

© www.soinside.com 2019 - 2024. All rights reserved.