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

问题描述 投票:0回答:3

当阅读第 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
会创建一个临时对象。

c++ derived-class static-cast effective-c++
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();
}

我希望

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)

请参阅此处了解更多详情。


0
投票

您的代码的问题是您没有修改

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,确认了该声明...


-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
}
© www.soinside.com 2019 - 2024. All rights reserved.