Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我们可以在C+;中使类副本构造函数成为虚拟的吗+; 可以在C++中实现类复制构造器吗?如何使用?_C++_Constructor_Virtual - Fatal编程技术网

我们可以在C+;中使类副本构造函数成为虚拟的吗+; 可以在C++中实现类复制构造器吗?如何使用?

我们可以在C+;中使类副本构造函数成为虚拟的吗+; 可以在C++中实现类复制构造器吗?如何使用?,c++,constructor,virtual,C++,Constructor,Virtual,不,你不能,构造函数不能是虚拟的 C++03-12.1构造函数 4) 构造函数不得是虚拟的(10.3)或静态的(9.4)。[……] 如果你需要这样的东西,你可以查一下虚拟构造函数的用法。,在C++中,不可能。不。C++是静态类型的语言,C++编译器对多态性的创建是没有意义的。编译器必须知道创建对象的类类型。换句话说,要创建什么类型的对象是从C++编译器角度编译时间的决定。如果我们将构造函数设为虚拟,编译器将标记一个错误 不,你不能 此外,整个概念没有意义。虚拟函数是基于对象的值(对象的动态类型)

不,你不能,构造函数不能是虚拟的

C++03-12.1构造函数

4) 构造函数不得是虚拟的(10.3)或静态的(9.4)。[……]


如果你需要这样的东西,你可以查一下虚拟构造函数的用法。

,在C++中,不可能。

不。C++是静态类型的语言,C++编译器对多态性的创建是没有意义的。编译器必须知道创建对象的类类型。换句话说,要创建什么类型的对象是从C++编译器角度编译时间的决定。如果我们将构造函数设为虚拟,编译器将标记一个错误

不,你不能

此外,整个概念没有意义。虚拟函数是基于对象的值(对象的动态类型)调度的函数。调用构造函数时,对象还没有值(因为它还没有被构造)。因此,不可能发生虚拟调度


想想看。这样的构造函数会有什么语义?

您不能,因为内存是根据新类型的大小而不是复制操作数在调用构造函数之前分配的。如果它真的起作用,那将是一个特例,许多语言结构的反向多态性

<>但是这并不意味着它不能用一个C++的魔法来完成。p> 在一些情况下,它非常有用,例如序列化非POD类。此示例创建一个虚拟副本构造函数,该构造函数使用新的放置方式工作

警告:这是一个可能帮助某些用户解决特定问题的示例。不要在通用代码中执行此操作。如果为新类分配的内存小于派生类,它将崩溃。最好(也是唯一)安全的使用方法是管理自己的类内存并使用新的位置

class VirtualBase
{
public: 
    VirtualBase() {}
    virtual ~VirtualBase() {}

    VirtualBase(const VirtualBase& copy)
    {
        copy.VirtualPlacementCopyConstructor(this);
    }

    virtual void VirtualPlacementCopyConstructor(void*) const {}
};

class Derived :: public VirtualBase
{
public:
    ...

    Derived(const Derived& copy) : ... don't call baseclass and make an infinite loop
    {
    }

protected:
    void VirtualPlacementCopyConstructor(void* place) const
    {
        new (place) Derived(*this);
    }
};

是的,您可以创建虚拟副本构造函数,但不能创建虚拟构造函数

原因:

<>虚拟构造函数:-不可能,因为C++是静态类型语言,并且将构造函数作为虚拟创建,所以编译器不能决定虚拟对象的类型,并因为虚拟关键字而离开整个运行过程。 编译器必须知道创建对象的类类型。换句话说,要创建什么类型的对象是从C++编译器角度编译时间的决定。如果我们将构造函数设为虚拟,编译器将标记一个错误


<>虚拟复制构造器:-是可能的,考虑剪贴板应用程序。剪辑板可以容纳不同类型的对象,并从现有对象复制对象,将其粘贴到应用程序画布上。同样,要复制的对象类型是运行时决定的。虚拟副本构造函数填补了这一空白

不完全正确,请参阅抽象工厂模式。假设您可以。。。构造函数调用应该调度到哪种类型?@DavidRodríguez dribeas的副本:这是一个很好的观点。我认为这应该是一个答案,因为它也解释了rationale@DavidRodríguez dribeas:Luchian答案中的c++常见问题链接提供了一个答案。我不介意直接在语言中使用它,而不必提供create()和clone()(比如在下一个标准中)。@stefaanv,nawaz:我知道这个成语,这个注释的意思是让你认为构造函数被应用到了一个尚未创建的对象上(此时它只分配了内存),并且C++中的调度应用于调用该方法的对象(此时仅为内存块)。该习惯用法颠倒了顺序,并对源对象使用虚拟分派,而不是对有效对象的目标对象使用虚拟分派。目的是让用户思考所问的问题。当这个习惯用法成为标准的一部分时,我不会打赌。你的链接是禁止的。虽然在大多数情况下,用虚拟方法解决它是可以的,但重要的是,它们不是构造函数,它是一个抽象工厂。这不会编译,即使你修复它使它编译,执行情况相当彻底。
派生的
的所有成员都将遭受双重初始化。这可能发生在一些简单类型上,但显然会导致未定义的行为。“构造函数”需要是
void VirtualPlacementCopyConstructor(VirtualBase*place)const{auto d=dynamic_cast(place);如果(d){d->~Derived();new(d)Derived(*this);}}}
现在应该很清楚问题是什么:调用
VirtualPlacementCopyConstructor
太早了,当复制到类的类型尚未派生时。因此,析构函数也不会做正确的事情,您会得到大量未定义的行为。如果您将
动态\u cast
替换为
静态\u cast
,则POD类型的情况将正常,仅此而已。一旦你添加了一个例如
std::string
成员,东西就会坏掉(更糟糕的是:它不会总是坏掉,所以你会感到毛骨悚然)。感谢你解释为什么不可能创建虚拟构造函数。语言是否允许使用虚拟副本构造函数与概念是否应该可行不同。