虚拟继承和移动构造函数

时间:2015-01-07 10:36:49

标签: c++ inheritance c++11 move-semantics virtual-inheritance

我用clang ++(3.5-1ubuntu1)观察奇怪的行为。 如果使用虚拟继承,则复制构造函数 “基础”类似乎被跳过。请看样品 以及结果如下。

需要复杂的继承层次结构, 它来自使用std流和streambufs的应用程序。

问题:

  • 在foo初始化之后,foo.x的值应该是多少?
  • 为什么在正常而不是虚拟继承时结果会发生变化 用来?请注意,没有涉及多重继承,所以我会 期待没有区别。
  • 我是否在调用未定义的行为?如果是的话,在哪里?如果是,可以 编译器警告它吗?

#include <iostream>

struct Base {
  int x;
  Base() : x(0) {}

  Base(Base const& other) : x(other.x) {
    std::cout << "Base::Base(Base const&)" << std::endl;
  }
};

// If virtual is removed, it works.
   struct Derived1 : virtual Base {
// struct Derived1 :         Base {
  Derived1(Derived1&& other) : Base(static_cast<const Base&>(other)) {
    std::cout << "MOVE constructor: other.x = " << other.x
              << ", this->x = " << x << std::endl;
  }

  Derived1() {
    x = 4711;
    std::cout << "DEFAULT constructor: x = " << x << std::endl;
  }
} ;

template< typename B >
struct Derived2 : B {
  // Deliberately invoke move constructor
  Derived2() : B( B() ) { }
} ;

int main() {
  Derived2<Derived1> foo ;

  // Expected: 4711, actual: 0
  std::cout << "foo.x = " << foo.x << std::endl;

  std::cout << "sizeof(Base) = " << sizeof(Base) << std::endl;
  std::cout << "sizeof(Derived1) = " << sizeof(Derived1) << std::endl;
  std::cout << "sizeof(foo) = " << sizeof(foo) << std::endl;

  // As expected, all addresses are equal, regardless whether virtual 
  // inheritance is used or not.
  std::cout << "&Derived2::x = " << &foo.x << std::endl;
  std::cout << "&Derived1::x = " << &static_cast<Derived1 const&>(foo).x << std::endl;
  std::cout << "&Base::x = " << &static_cast<Base const&>(foo).x << std::endl;
}

我得到的结果:

DEFAULT constructor: x = 4711
MOVE constructor: other.x = 4711, this->x = 0
foo.x = 0
sizeof(Base) = 4
sizeof(Derived1) = 16
sizeof(foo) = 16
&Derived2::x = 0x7fff7a445338
&Derived1::x = 0x7fff7a445338
&Base::x = 0x7fff7a445338

0 个答案:

没有答案