C++ 为什么没有用户的类提供cp/mv-ctor,并且具有虚拟函数,但没有虚拟基,而没有“繁琐的cp/mv-ctor”?
根据标准: 如果类X的复制/移动构造函数不是用户提供的,并且 -类X没有虚拟函数10.3和虚拟基类10.1,以及 -选择用于复制/移动每个直接基类子对象的构造函数非常简单,并且 -对于类类型或其数组的X的每个非静态数据成员,构造函数 选择复制/移动该成员是微不足道的 否则,复制/移动构造函数是非常重要的 我认为标准引入了trival cp/mv ctor的概念,以推断您可以使用std::memcpy而不是调用构造函数来复制类,并且不会有未定义的行为 然而,该标准不允许虚拟函数的存在,我认为这与繁琐的cp/mv的精神背道而驰。带有指向虚拟函数的vtable的类仍然可以使用std::memcpy进行复制,并且具有正确的行为。毕竟,您不能在运行时更改一个类的vtable,这将破坏该类的其他实例C++ 为什么没有用户的类提供cp/mv-ctor,并且具有虚拟函数,但没有虚拟基,而没有“繁琐的cp/mv-ctor”?,c++,c++11,language-lawyer,C++,C++11,Language Lawyer,根据标准: 如果类X的复制/移动构造函数不是用户提供的,并且 -类X没有虚拟函数10.3和虚拟基类10.1,以及 -选择用于复制/移动每个直接基类子对象的构造函数非常简单,并且 -对于类类型或其数组的X的每个非静态数据成员,构造函数 选择复制/移动该成员是微不足道的 否则,复制/移动构造函数是非常重要的 我认为标准引入了trival cp/mv ctor的概念,以推断您可以使用std::memcpy而不是调用构造函数来复制类,并且不会有未定义的行为 然而,该标准不允许虚拟函数的存在,我认为这与繁
那么,为什么没有用户的类不能提供cp/mv-ctor并具有虚拟函数,但没有虚拟基的类却具有繁琐的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);
}
让我们假设基数很小。照你说的做。b的vptr指向派生的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的复制子对象平凡化?当您仅从派生对象复制基本子对象时会发生什么?我指的是memcpy,但cp/mv-ctor指的是从同一类型复制或移动数据。TIVAL的整个概念是建立在同一个类的基础上的,派生类或基类与此无关,考虑结构B {VirtualB{}};结构D:B{};dx;B y,*p;p=&x;memcpy&y,p,sizeof y@您可以有一个指向派生类的基类指针。在这种情况下,您将复制错误的vtable指针。