当阅读有效C++中的项目27最小化强制转换时,它说不要尝试使用static_cast
将派生类中的*this
强制转换为基类。因为static_cast<Base>(*this)
将创建基类的临时对象。我尝试了一个如下的例子,但是,它总是使用不同的编译器(如clang 3.8和gcc 4.9、5.3)输出10。
我错了吗?
#include <iostream>
class A {
public:
int a;
virtual void foo() {std::cout << a << std::endl;}
};
class B : public A {
public:
int b;
void foo () { static_cast<A>(*this).foo();}
};
int main () {
B b;
b.a = 10;
b.foo();
return 0;
}
问题是static_cast
为什么要创建一个临时对象。
一个更有意义的例子是:
#include <iostream>
class A {
public:
virtual void foo() { std::cout << "A" << std::endl; }
};
class B : public A {
public:
virtual void foo() { std::cout << "B" << std::endl; }
void bar () { static_cast<A>(*this).foo(); }
};
int main () {
B b;
b.bar();
}
我希望bar
打印B
,因为foo
是一个重写的方法。而是打印A
好吧,从语言的角度来看,这是正确的,从开发人员的角度来看就不那么好了,因为他们期待着完全不同的结果。
如果您使用以下类,它会起作用:
class B : public A {
public:
virtual void foo() { std::cout << "B" << std::endl; }
void bar () { static_cast<A*>(this)->foo(); }
};
以下一个也如预期一样有效(为了清晰起见,添加了一个,感谢评论中的@MORTAL):
class B : public A {
public:
virtual void foo() { std::cout << "B" << std::endl; }
void bar () { static_cast<A&>(*this).foo(); }
};
无论如何,您面临的问题被命名为切片
这就是为什么如果你不知道自己在做什么,就不鼓励使用static_cast<A>(*this)
。
请参阅此处了解更多详细信息。
您的代码的问题是您没有修改A
的a
变量的值,因此您看不到两个实例的值之间的变化。
为A
添加以下复制构造函数:
A() = default; // so that it still exists...
A(A const& other)
: a(other.a + 1) // initialise to a value definitely differing...
{ }
现在您应该看到11,确认声明。。。
首先,您不必强制转换Derived->Base,因为它是自动发生的。是的,static_cast将创建一个类型为的对象。在您的情况下,要启用多态性,您可以使用引用或指针:
int main(){
B b;
A &a = b; // no explicit cast needed
a.foo(); // will call B::foo
//OR
B *bPtr = new B;
A *aPtr = bPtr; // no explicit cast needed
aPtr->foo(); // same as above
}