当阅读第 27 条最小化Effective C++中的转换时,它说不要尝试使用
static_cast
将派生类中的*this
转换为基类。因为static_cast<Base>(*this)
会创建一个Base类的临时对象。我尝试了如下示例,但是,使用不同的编译器(例如 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
}