Can we make a class copy constructor virtual in C++
Asked Answered
E

7

42

Can we make a class copy constructor virtual in C++? How to use?

Educative answered 27/3, 2012 at 12:24 Comment(6)
Assuming that you could... which type should the constructor call be dispatched to?Scharaga
Duplicate of #733860Jingoism
@DavidRodríguez-dribeas: That is a good point. I think it should be an answer, as it also explains the rationalePops
@DavidRodríguez-dribeas: the c++faq link in Luchian's answer provides an answer. I wouldn't mind having it directly in the language instead of having to provide create() and clone() (say in the next standard).Bout
@stefaanv, nawaz: I know the idiom, the comment is meant to make you think that the constructor is applied to an object that is not yet created (at this point it is only allocated memory), and that dispatch in C++ is applied on the object of which the method is being called (at this point just a memory block). The idiom reverses the order, and uses virtual dispatch on the source object, rather than the destination, which is a valid object. The intention was making the user think on what was being asked. As of the idiom becoming part of the standard, I would not bet on it.Scharaga
@DavidRodríguez-dribeas: I already answered this to a previous question (stackoverflow.com/questions/1108008/any-ideas-for-c1y/…), but I'm not holding my breath...Bout
S
35

No you can't, constructors can't be virtual.

C++03 - 12.1 Constructors

4) A constructor shall not be virtual (10.3) or static (9.4). [...]

If you need something like this, you can look up the virtual constructor idiom here.

Schoolteacher answered 27/3, 2012 at 12:25 Comment(2)
your link is forbiddenCeroplastics
Although solving it with virtual methods can be in most cases okay, it is important to mention, that these are not constructors, it is an abstract factory.Stirling
W
6

No you cannot.

Furthermore, the whole concept does not make sense. Virtual functions are functions that are dispatched based on the value of an object (the dynamic type of the object). When a constructor is called, the object does not yet have a value (because it has not yet been constructed). Therefore, no virtual dispatch can possibly occur.

Think about it. What semantics would such a constructor have?

Wendalyn answered 27/3, 2012 at 12:38 Comment(1)
Thank you for explaining why NOT possible to create a virtual constructor.Inartistic
H
2

No. C++ being static typed language, it is meaningless to the C++ compiler to create an object polymorphically. The compiler must be aware of the class type to create the object. In other words, what type of object to be created is a compile time decision from C++ compiler perspective. If we make constructor virtual, compiler flags an error.

Hulbard answered 27/3, 2012 at 12:32 Comment(1)
Not entirely true, see abstract factory pattern.Schoolteacher
H
2

You cannot because the memory is allocated before the constructor is called based on the size of the new type not the copy operand. And if it did work it would be a special case that inverted polymorphism for a number of language constructs.

But that doesn't mean it can't be done with a little C++ magic. :)

There are couple cases where it is incredibly helpful, Serializing non-POD classes for instance. This example creates a virtual copy constructor that works using placement new.

Warning: This is an example that may help some users with specific problems. Do not do this in general purpose code. It will crash if the memory allocated for the new class is smaller than the derived class. The best (and only) safe way to use this is if you are managing your own class memory and using placement new.

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);
    }
};
Honorine answered 12/12, 2015 at 3:16 Comment(2)
This won't compile, even if you fix it to get it to compile, the implementation is rather thoroughly broken. All members of Derived will suffer from double initialization. This might happen to work with some simple types, but clearly results in undefined behavior. The "constructor" would need to be void VirtualPlacementCopyConstructor(VirtualBase* place) const { auto d = dynamic_cast<Derived*>(place); if (d) { d->~Derived(); new (d) Derived(*this); } }Codding
It should be now obvious what the problem is: the VirtualPlacementCopyConstructor is invoked way too early, when the type of the copied-into class is not Derived yet. Thus the destructor won't do the right thing either, and you get undefined behavior aplenty. If you replace dynamic_cast with static_cast, things will work for POD types, and that's about it. As soon as you add e.g. a std::string member, stuff will break (worse yet: it won't always break, so you'll be pulling your hair out).Codding
D
0

Never, it won't possible in C++.

Duval answered 27/3, 2012 at 12:30 Comment(0)
P
0

The solution being worked on by those close to the standards committee is the value_types proposal. You will still not directly be able to copy polymorphic types. However with a wrapper it becomes trivial to copy any polymorphic type.

That is with class Base and class Derived : public Base you construct Derived instances like so, with arg0 and arg1 being arguments to Deriveds constructor.

std::polymorphic<Base> v = 
  std::polymorphic<Base>(
    std::in_place_type_t<Derived>{}, 
    arg0, 
    arg1
  );

and can then simply copy the value around

auto v2 = v;

without any risk of slicing.

https://github.com/jbcoe/value_types

For example, the below code shows the copying of polymorphic types without any extra clone or deepcopy virtual members. The requirement is just to construct the object into a polymorphic wrapper which captures the constructor of the real type.

https://godbolt.org/z/1fbxE7Pxc

#include <https://raw.githubusercontent.com/jbcoe/value_types/main/indirect.h>
#include <https://raw.githubusercontent.com/jbcoe/value_types/main/polymorphic.h>
#include <vector>
#include <utility>

class Base {
public:
    Base(){}
    virtual int foo() = 0;
    virtual ~Base() = default;
};

class Child : public Base {
public:
    Child(int _x):x(_x){}
    int foo() override { return x;}
    int x;
};

class Child2 : public Base {
public:
    Child2(int _y):y(_y){}
    int foo() override { return y;}
    int y;
};


int main()
{
    std::vector<xyz::polymorphic<Base>> vec;
    vec.push_back(xyz::polymorphic<Base>(Child(189)));
    vec.push_back(xyz::polymorphic<Base>(Child(97)));
    vec.push_back(xyz::polymorphic<Base>(std::in_place_type_t<Child2>{},66));

    assert(vec[0]->foo() == 189);
    assert(vec[1]->foo() == 97);
    assert(vec[2]->foo() == 66);

    auto b = vec;

    assert(b[0]->foo() == 189);
    assert(b[1]->foo() == 97);
    assert(b[2]->foo() == 66);

}

For a slightly simpler implementation than in the official repo one can inspect

https://godbolt.org/z/sT7asfozG

to see how one would go about creating such a system. The central idea is to capture a function pointer with the signature.

    template <typename DerivedT>
    requires std::convertible_to<DerivedT*,BaseT*>
    static std::unique_ptr<BaseT> CopyFunction(BaseT const& v) {
        return std::make_unique<DerivedT>(*static_cast<DerivedT const*>(&v));
    }

which is just type erasing a function pointer implementing

std::make_unique<DerivedT>(vDerived)

and storing the function pointer in a control block so that even though the wrapper manifests as polymorphic<Base> internally it holds the function pointer for copying Derived

Peristome answered 24/4, 2024 at 7:52 Comment(0)
M
-2

Yes you can create virtual copy constructor but you can not create virtual constructor.

Reason:

Virtual Constructor:- Not Possible because c++ is static type language and create constructor as a virtual so compiler won't be able to decide what type of object it and leave the whole process for run time because of virtual keyword. The compiler must be aware of the class type to create the object. In other words, what type of object to be created is a compile time decision from C++ compiler perspective. If we make constructor virtual, compiler flags an error.

Virtual Copy constructor:- Yes Possible, consider clip board application. A clip board can hold different type of objects, and copy objects from existing objects, pastes them on application canvas. Again, what type of object to be copied is a runtime decision. Virtual copy constructor fills the gap here.

Mastaba answered 11/7, 2018 at 11:1 Comment(1)
Whether the language permits using virtual copy constructor is different from whether the concept should be possible.Sharilyn

© 2022 - 2025 — McMap. All rights reserved.