为什么static_cast不能从虚拟基地垂头丧气?
struct A {};
struct B : public virtual A {};
struct C : public virtual A {};
struct D : public B, public C {};
int main()
{
D d;
A& a = d;
D* p = static_cast<D*>(&a); //error
}
Run Code Online (Sandbox Code Playgroud)
g ++ 4.5说:
error: cannot convert from base ‘A’ to derived type ‘D’ via virtual base ‘A’
Run Code Online (Sandbox Code Playgroud)
解决方案是使用dynamic_cast?但为什么.什么是理性?
- 编辑 -
下面非常好的答案.没有答案详细说明子对象和vtable最终如何订购.以下文章为gcc提供了一些很好的例子:http:
//www.phpcompiler.org/articles/virtualinheritance.html#Downcasting
静态演员的描述说
如果new_type是右值引用类型,则static_cast将expression的值转换为xvalue.这种类型的static_cast用于在std :: move中实现移动语义.(自C++ 11起)
这是否证实以下内容相同?
(一个)
X x1;
X x2 = static_cast<X&&>(x1);
Run Code Online (Sandbox Code Playgroud)
(B)
X x1;
X x2 = std::move(x1);
Run Code Online (Sandbox Code Playgroud) 对于以下代码,除最后一个断言外,所有代码均通过:
template<typename T>
constexpr void assert_static_cast_identity() {
using T_cast = decltype(static_cast<T>(std::declval<T>()));
static_assert(std::is_same_v<T_cast, T>);
}
int main() {
assert_static_cast_identity<int>();
assert_static_cast_identity<int&>();
assert_static_cast_identity<int&&>();
// assert_static_cast_identity<int(int)>(); // illegal cast
assert_static_cast_identity<int (&)(int)>();
assert_static_cast_identity<int (&&)(int)>(); // static assert fails
}
Run Code Online (Sandbox Code Playgroud)
为什么最后一个断言失败,static_cast<T>而不总是返回a T?
请参阅下面的代码.
a)在这种情况下(简单继承,没有虚拟成员),B :: df()中的静态强制转换是否有任何开销(无论如何)?我找到了类似问题的一些相互矛盾的答案,这就是我要问的原因......
b)我正在考虑const M1 * func在A中私有化并在B中引入一个新的私有字段const M2 * func来避免演员表,但它使事情变得复杂并且更难以使用智能指针.你有没有看到避免演员的更好方法?
class M1 {
public:
double f() const;
};
class M2 : public M1 {
public:
double df() const;
};
class A {
protected:
const M1 * func;
public:
A(const M1 * p);
~A();
double f() const;
};
class B : public A {
public:
B(const M2 * p);
double df() const;
};
double M1::f() const { return 1973.0; }
double M2::df() const { return 0.0; …Run Code Online (Sandbox Code Playgroud) 令我惊讶的是,gcc 11.2接受此代码,但仅在 C++20 模式下:
struct Base {};
struct Derived : Base { int i; };
int f(Base& b) { return static_cast<Derived>(b).i; }
// ^~~~~~~ oops, forgot the `&`
Run Code Online (Sandbox Code Playgroud)
同样,MSVC 19.29 在 C++20 模式下接受它,在 C++17 模式下拒绝它,但即使在 C++20 模式下,clang 也会拒绝它。
查看汇编器输出,f总是返回0,因此它忽略了Derived传递给的任何潜在的实际数据f。
这是 UB,还是在 C++20 中合法,如果是,为什么?
当我尝试使用static_cast将double*转换为int*时,我收到以下错误:
invalid static_cast from type ‘double*’ to type ‘int*’
Run Code Online (Sandbox Code Playgroud)
这是代码:
#include <iostream>
int main()
{
double* p = new double(2);
int* r;
r=static_cast<int*>(p);
std::cout << *r << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
我理解在double和int之间转换会有问题,但为什么在double*和int*之间转换有问题?
我有一个T * pValues我想要查看的指针T (&values)[N]
在这个SO答案/sf/answers/184449611/中,建议的方法是
T (&values)[N] = *static_cast<T(*)[N]>(static_cast<void*>(pValues));
Run Code Online (Sandbox Code Playgroud)
我对此的担忧是.在他的例子中,pValues以下面的方式初始化
T theValues[N];
T * pValues = theValues;
Run Code Online (Sandbox Code Playgroud)
我的问题是,如果pValues来自以下任何构造,则构造构造是否合法:
T theValues[N + M]; // M > 0
T * pValues = theValues;
Run Code Online (Sandbox Code Playgroud)
T * pValues = new T[N + M]; // M >= 0
Run Code Online (Sandbox Code Playgroud) 简单的问题:从 int(例如 100)转换为双精度数“向上或向下舍入”到下一个双精度数,还是总是舍入到最接近的一个(最小增量)?
例如static_cast<double>(100):
如果 d2 < d1 会向哪个方向投射?
额外问题:我可以以某种方式强制处理器使用特殊函数向下或向上“舍入”到双精度吗?据我所知,没有floor<double>或者ceil<double>不幸的是。
c++ floating-point rounding static-cast floating-point-conversion
让我们有一个名为Y的函数重载:
void Y(int& lvalue)
{ cout << "lvalue!" << endl; }
void Y(int&& rvalue)
{ cout << "rvalue!" << endl; }
Run Code Online (Sandbox Code Playgroud)
现在,让我们定义一个像std :: forward一样的模板函数
template<class T>
void f(T&& x)
{
Y( static_cast<T&&>(x) ); // Using static_cast<T&&>(x) like in std::forward
}
Run Code Online (Sandbox Code Playgroud)
现在看看main()
int main()
{
int i = 10;
f(i); // lvalue >> T = int&
f(10); // rvalue >> T = int&&
}
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,输出是
lvalue!
rvalue!
Run Code Online (Sandbox Code Playgroud)
现在回到模板功能f()并替换static_cast<T&&>(x)为static_cast<T>(x).让我们看看输出:
lvalue!
rvalue!
Run Code Online (Sandbox Code Playgroud)
一样的!为什么?如果它们是相同的,那么为什么std::forward<>从返回一个投x来 …
我有一些像这样的代码
struct B
{
B() {}
B(int v) {}
};
struct A
{
operator int() const { return 1; }
operator B() const { return B(); }
};
int main()
{
A a;
static_cast<B>(a); // Error here
a.operator B(); // This is OK
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它会产生这样的编译错误:
main.cpp: In function ‘int main()’:
main.cpp:16:21: error: call of overloaded ‘B(A&)’ is ambiguous
static_cast<B>(a);
^
main.cpp:4:5: note: candidate: B::B(int)
B(int v) {}
^
main.cpp:1:8: note: candidate: constexpr B::B(const B&)
struct B
^
main.cpp:1:8: …Run Code Online (Sandbox Code Playgroud)