我有以下代码(从virtual functions and static_cast被盗):
#include <iostream>
class Base
{
public:
virtual void foo() { std::cout << "Base::foo() \n"; }
};
class Derived : public Base
{
public:
virtual void foo() { std::cout << "Derived::foo() \n"; }
};
如果我有:
int main()
{
Base base;
Derived& _1 = static_cast<Derived&>(base);
_1.foo();
}
打印输出为:Base::foo()
但是,如果我有:
int main()
{
Base * base;
Derived* _1 = static_cast<Derived*>(base);
_1->foo();
}
打印输出为:Segmentation fault: 11
Derived::foo()
”,我该怎么办?
答案 0 :(得分:5)
在你的第二个例子中,你是段错误,因为你没有实例化你的基指针。所以没有v-table可以调用。尝试:
Base * base = new Base();
Derived* _1 = static_cast<Derived*>(base);
_1->foo();
这将打印Base :: foo()
这个问题毫无意义,因为static_cast不会影响v-table。但是,这对非虚函数更有意义:
class Base
{
public:
void foo() { std::cout << "Base::foo() \n"; }
};
class Derived : public Base
{
public:
void foo() { std::cout << "Derived::foo() \n"; }
};
int main()
{
Base base;
Derived& _1 = static_cast<Derived&>(base);
_1.foo();
}
这个将输出Derived :: foo()。然而,这是非常错误的代码,虽然它编译,但行为未定义。
答案 1 :(得分:5)
指针或引用类型的有效static_cast
根本不会影响虚拟调用。根据对象的动态类型解析虚拟调用。指针或引用的static_cast
不会改变实际对象的动态类型。
您在示例中观察到的输出无关紧要。这些例子很简单。
第一个无效static_cast
。在底层对象不是Base &
的情况下,您不能将Derived &
强制转换为Derived
。任何执行此类转换的尝试都会产生不确定的行为。
以下是static_cast
对参考类型向下转型的有效应用示例
int main()
{
Derived derived;
Base &base = derived;
Derived& _1 = static_cast<Derived&>(base);
_1.foo();
}
在您的第二个示例中,代码完全被破坏,原因与任何强制转换或虚拟调用无关。代码试图操纵非初始化的指针 - 行为未定义。
答案 2 :(得分:2)
虚函数的整个目的是变量的静态类型无关紧要。编译器将查找对象本身的实际实现(通常使用隐藏在对象中的vtable指针)。 static_cast
应该没有效果。
答案 3 :(得分:2)
在这两个示例中,行为都是未定义的。 Base
对象不是Derived
对象,并告诉编译器假装它不是一个对象。获取代码打印"Derived::foo()"
的方法是使用Derived
类型的对象。