1

在阅读 Item 27 Minimize cast in Effective C++时,它说不要尝试使用static_cast*this派生类转换为基类。因为static_cast<Base>(*this)会创建一个基类的临时对象。我尝试了一个如下示例,但是,它始终使用不同的编译器输出 10,例如 clang 3.8 和 gcc 4.9、5.3。

我错了吗?

  #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会创建一个临时对象。

4

3 回答 3

2

一个更有意义的例子是这个:

#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();
}

我希望barprint B, forfoo是一个被覆盖的方法。而是打印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(); }
};

无论如何,您面临的问题名为slicing
这就是为什么static_cast<A>(*this)如果您不知道自己在做什么,就不鼓励使用。

有关详细信息,请参见此处

于 2016-04-28T22:24:59.400 回答
0

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

为 添加以下复制构造函数A

A() = default; // so that it still exists...
A(A const& other)
    : a(other.a + 1) // initialise to a value definitely differing...
{ }

现在您应该看到 11,确认声明...

于 2022-02-04T11:27:30.333 回答
-1

首先,您不必强制转换 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
}
于 2016-04-28T22:24:58.530 回答