static_cast将此对象派生到C++中的基类



当阅读有效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)

请参阅此处了解更多详细信息。

您的代码的问题是您没有修改Aa变量的值,因此您看不到两个实例的值之间的变化。

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
}

最新更新