繁体   English   中英

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

[英]Why do classes with no user-provide cp/mv ctor and have virtual functions but no virtual bases not have “trival cp/mv ctor”?

根据标准:

如果类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”呢?

这不是普通类型,因为确保“ 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。 我们称为覆盖函数。

繁荣!

考虑一个简单的例子:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM