为什么没有用户提供cp / mv ctor且具有虚拟功能但没有虚拟基础的类没有" trival cp / mv ctor"?

时间:2018-03-25 08:00:40

标签: c++ c++11 language-lawyer

根据标准:

  

如果不是用户提供的,并且如果

,则类X的复制/移动构造函数是微不足道的      

- 类X没有虚函数(10.3),没有虚基类(10.1)和

     

- 选择复制/移动每个直接基类子对象的构造函数是微不足道的,

     

- 对于类型(或其数组)的X的每个非静态数据成员,构造函数   选择复制/移动该成员是微不足道的;

     

否则复制/移动构造函数不重要。

我认为该标准引入了概念" trival cp / mv ctor"推断你可以使用std :: memcpy而不是调用构造函数来复制类,并且没有未定义的行为。

然而,该标准并不允许虚拟功能的存在,我认为这违反了&t 34 / t 34 / trv ctor / m 34的精神。具有指向虚函数的vtable的类仍然可以使用std :: memcpy复制并具有正确的行为。毕竟,您无法在运行时更改类的vtable - 这将破坏此类的其他实例。

那么,为什么没有用户提供cp / mv ctor且具有虚拟功能但没有虚拟基础的类具有" trival cp / mv ctor"?

2 个答案:

答案 0 :(得分:3)

这不是一个微不足道的类型,因为确保“vptr”指向正确的“vtable”并不像复制指针的值那么简单。我们可以复制只是基础子对象。我们不需要总是处理最派生的对象类型。

void bar(base const& b) { 
  b.overriden_function();
}

void foo(base const& b) {
  auto other_b = b;
  bar(other_b);
}

int main() {
  derived d;
  foo(d);
}

我们假设base 是微不足道的。所以副本就像你说的那样完成。 b的vptr指向derived的vtable。所以现在我们获得了一个vtpr指向错误vtable的对象。我们称之为覆盖函数。

轰!

答案 1 :(得分:1)

考虑一个简单的例子:

#include <iostream>

struct ConcreteBase {
    virtual void method() {
        std::cout << "Basic implementation" << std::endl;
    }
};
struct Derived: ConcreteBase {
    Derived(int x): extraState{x} {}
    void method() {
        std::cout << "Overridden (" << extraState << ')' << std::endl;
    }
private:
    const int extraState;
};

int main() {
    ConcreteBase const &b = Derived(42);
    ConcreteBase b1{b};
    b1.method();
}

你究竟如何使用memcpy来复制vtable? (更广泛地说,你如何轻视ConcreteBase的复制?)