首页 文章

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

提问于
浏览
2

根据标准:

如果类X不是用户提供的,那么类X的复制/移动构造函数是微不足道的 - 如果 - 类X没有虚函数(10.3)而没有虚函数基类(10.1),并且 - 构造函数选择复制/移动每个直接基类子对象是微不足道的,并且 - 对于类类型(或其数组)的X的每个非静态数据成员,选择复制/移动该成员的构造函数是微不足道的;否则复制/移动构造函数是非平凡的 .

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

但是,该标准不允许存在虚函数,我认为这违背了“trival cp / mv ctor”的精神 . 具有指向虚函数的vtable的类仍然可以使用std :: memcpy复制并具有正确的行为 . 毕竟,您无法在运行时更改类的vtable - 这将破坏此类的其他实例 .

那么,为什么不能没有用户提供cp / mv ctor并且具有虚拟功能而没有虚拟基础的类具有“trival cp / mv ctor”?

2 回答

  • 1

    这不是一个微不足道的类型,因为确保"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的对象 . 我们称之为覆盖函数 .

    繁荣!

  • 3

    考虑一个简单的例子:

    #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的复制文件?)

相关问题