我试图将基类指针转换为派生类对象。我可以使用旧样式进行投射,但不能使用新样式。我发现了一些类似的问题,但找不到答案。
下面是我的问题的缩小示例。
这行((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;
};
答案 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。