如何将const基类指针转换为派生类

时间:2019-01-25 14:26:57

标签: c++

我试图将基类指针转换为派生类对象。我可以使用旧样式进行投射,但不能使用新样式。我发现了一些类似的问题,但找不到答案。

下面是我的问题的缩小示例。 这行((Scalar<int>*)base)->get();给了我正确的结果。 这行static_cast<Scalar<int>*>(base)->get();会导致编译器错误:错误:从类型'const Base *'到类型'Scalar *'的static_cast丢弃了限定符

class Base
{
    public:
    Base() {};
    virtual ~Base() {};
    int getID() const { return 1; };
};


template<class T> class Scalar : public Base
{
    public:
        Scalar() {};
        ~Scalar() {};
        void set(const T value)
        {
            m_value = value;
        }
        T get() const { return m_value; }
    private:
        T m_value;
};


class Access
{
public:
    const Base *find() const
    {
        return &m_scalar;
    }

    void example()
    {
        m_scalar.set(25);

        const Base *base = find();

        int res1 = ((Scalar<int>*)base)->get();
        int res2 = static_cast<Scalar<int>*>(base)->get();


        std::cout << res1 << std::endl;
        std::cout << res2 << std::endl;

    }
private:
    Scalar<int> m_scalar;
};

3 个答案:

答案 0 :(得分:7)

这样做的时候

int res1 = ((Scalar<int>*)base)->get();

您执行所谓的C样式转换。之所以可行,是因为c样式的强制类型转换不做任何检查,而忽略了const的强制类型转换。他们只是将源类型强制转换为目标类型,而不会产生任何后果。

另一方面,static_cast实际上检查您在做什么,并且看到您正在尝试消除base的常数性。除const_cast以外的任何强制类型转换都不允许这样做,因此会出现错误。我们可以在这里使用它来摆脱常量性,但这不是必需的。您可以使用

将其强制转换为const Scalar<int>*
int res2 = static_cast<const Scalar<int>*>(base)->get();

答案 1 :(得分:4)

您错过了const

static_cast<Scalar<int> const*>(base)->get();

我强烈建议避免在C ++代码中使用C样式强制转换,因为当参数类型更改时,强制转换的确切语义可能会无提示地更改。 See what C-style cast does

答案 2 :(得分:4)

编译器错误几乎可以解决这个问题,您无法使用const丢弃get()返回的static_cast形式。因此:

static_cast<const Scalar<int> *>(base)->get();

请记住,抛弃const通常是一种代码味道,另请参阅ES.50