ChatGPT解决这个技术问题 Extra ChatGPT

Why do we not have a virtual constructor in C++?

Why does C++ not have a virtual constructor?

If C++ did have virtual constructors, how would you use them?
virtual functions aid in dynamic binding -> which happens at run-time -> objects are created at run-time -> objects creation requires constructor. If this ctor was virtual, the dog would start chasing its own tail (the dog being the poor compiler :p)
@RSahu: Most likely, whoever asks for a virtual constructor in C++ has the idea in their mind it's a copy constructor and it will dynamically invoke based on the argument to the copy constructor. It makes logical sense but C++ can't handle virtual dispatch via an instance that is not a pointer, nor the dynamic stack (or worse static) memory implied.

M
Marc.2377

Hear it from the horse's mouth. :)

From Bjarne Stroustrup's C++ Style and Technique FAQ Why don't we have virtual constructors?

A virtual call is a mechanism to get work done given partial information. In particular, "virtual" allows us to call a function knowing only any interfaces and not the exact type of the object. To create an object you need complete information. In particular, you need to know the exact type of what you want to create. Consequently, a "call to a constructor" cannot be virtual.

The FAQ entry goes on to give the code for a way to achieve this end without a virtual constructor.


Is it possible to force derived classes to have a constructor without arguments ?
A
Anton Gogolev

Virtual functions basically provide polymorphic behavior. That is, when you work with an object whose dynamic type is different than the static (compile time) type with which it is referred to, it provides behavior that is appropriate for the actual type of object instead of the static type of the object.

Now try to apply that sort of behavior to a constructor. When you construct an object the static type is always the same as the actual object type since:

To construct an object, a constructor needs the exact type of the object it is to create [...] Furthermore [...]you cannot have a pointer to a constructor

(Bjarne Stroustup (P424 The C++ Programming Language SE))


"you cannot have a pointer to a constructor" A "pointer to a constructor" has as much runtime information as an empty struct, because constructors do not have names.
@curiousguy: A pointer to constructor makes perfect sense. If you had one it would act like placement new.
@Joshua Then... use placement new. What's the use case?
P
Pete Kirkham

Unlike object oriented languages such as Smalltalk or Python, where the constructor is a virtual method of the object representing the class (which means you don't need the GoF abstract factory pattern, as you can pass the object representing the class around instead of making your own), C++ is a class based language, and does not have objects representing any of the language's constructs. The class does not exist as an object at runtime, so you can't call a virtual method on it.

This fits with the 'you don't pay for what you don't use' philosophy, though every large C++ project I've seen has ended up implementing some form of abstract factory or reflection.


This is exactly the difference between construction in C++ and in a language such as Delphi, where you do have virtual constructors. Well put.
I was wondering how the question even made sense until I read this explanation of how object creation works in other languages. +1.
"Advanced C++" by James Coplien talks about how to implement virtual constructors in C++ (e.g., new animal("dog")). See users.rcn.com/jcoplien/Patterns/C++Idioms/… for some more information on how it's implemented
u
user88637

two reasons I can think of:

Technical reason

The object exists only after the constructor ends.In order for the constructor to be dispatched using the virtual table , there has to be an existing object with a pointer to the virtual table , but how can a pointer to the virtual table exist if the object still doesn't exist? :)

Logic reason

You use the virtual keyword when you want to declare a somewhat polymorphic behaviour. But there is nothing polymorphic with constructors , constructors job in C++ is to simply put an object data on the memory . Since virtual tables (and polymorphism in general) are all about polymorphic behaviour rather on polymorphic data , There is no sense with declaring a virtual constructor.


virtual destructor does not show polymorphic behaviour? you sure about 2nd reason?
How are vtable updated? Do they really need vptr to be updated?
C
Community

Summary: the C++ Standard could specify a notation and behaviour for "virtual constructor"s that's reasonably intuitive and not too hard for compilers to support, but why make a Standard change for this specifically when the functionality can already be cleanly implemented using create() / clone() (see below)? It's not nearly as useful as many other language proposal in the pipeline.

Discussion

Let's postulate a "virtual constructor" mechanism:

Base* p = new Derived(...);
Base* p2 = new p->Base();  // possible syntax???

In the above, the first line constructs a Derived object, so *p's virtual dispatch table can reasonably supply a "virtual constructor" for use in the second line. (Dozens of answers on this page stating "the object doesn't yet exist so virtual construction is impossible" are unnecessarily myopically focused on the to-be-constructed object.)

The second line postulates the notation new p->Base() to request dynamic allocation and default construction of another Derived object.

Notes:

the compiler must orchestrate memory allocation before calling the constructor - constructors normally support automatic (informally "stack") allocation, static (for global/namespace scope and class-/function-static objects), and dynamic (informally "heap") when new is used the size of object to be constructed by p->Base() can't generally be known at compile-time, so dynamic allocation is the only approach that makes sense it is possible to allocate runtime-specified amounts of memory on the stack - e.g. GCC's variable-length array extension, alloca() - but leads to significant inefficiencies and complexities (e.g. here and here respectively)

the size of object to be constructed by p->Base() can't generally be known at compile-time, so dynamic allocation is the only approach that makes sense it is possible to allocate runtime-specified amounts of memory on the stack - e.g. GCC's variable-length array extension, alloca() - but leads to significant inefficiencies and complexities (e.g. here and here respectively)

it is possible to allocate runtime-specified amounts of memory on the stack - e.g. GCC's variable-length array extension, alloca() - but leads to significant inefficiencies and complexities (e.g. here and here respectively)

for dynamic allocation it must return a pointer so memory can be deleted later.

the postulated notation explicitly lists new to emphasise dynamic allocation and the pointer result type.

The compiler would need to:

find out how much memory Derived needed, either by calling an implicit virtual sizeof function or having such information available via RTTI

call operator new(size_t) to allocate memory

invoke Derived() with placement new.

OR

create an extra vtable entry for a function that combines dynamic allocation and construction

So - it doesn't seem insurmountable to specify and implement virtual constructors, but the million-dollar question is: how would it be better than what's possible using existing C++ language features...? Personally, I see no benefit over the solution below.

`clone()` and `create()`

The C++ FAQ documents a "virtual constructor" idiom, containing virtual create() and clone() methods to default-construct or copy-construct a new dynamically-allocated object:

class Shape {
  public:
    virtual ~Shape() { } // A virtual destructor
    virtual void draw() = 0; // A pure virtual function
    virtual void move() = 0;
    // ...
    virtual Shape* clone() const = 0; // Uses the copy constructor
    virtual Shape* create() const = 0; // Uses the default constructor
};
class Circle : public Shape {
  public:
    Circle* clone() const; // Covariant Return Types; see below
    Circle* create() const; // Covariant Return Types; see below
    // ...
};
Circle* Circle::clone() const { return new Circle(*this); }
Circle* Circle::create() const { return new Circle(); }

It's also possible to change or overload create() to accept arguments, though to match the base class / interface's virtual function signature, arguments to overrides must exactly match one of the base class overloads. With these explicit user-provided facilities, it's easy to add logging, instrumentation, alter memory allocation etc..


The difference is that these clone and create functions don't work with containers, don't work with pass by value, etcetera. So they don't achieve what we want -- polymorphism without slicing while preserving ordinary value semantics.
@DavidSchwartz: clone and create don't work directly with Standard containers, but it's trivial to write a small management type that clones from the copy constructor etc (e.g. see here). Such management objects can also be passed around by value if you find that easier than using references. With clone / create private and the management object be-friend-ed, you can ensure consistent use. Still, it's true that that's an extra layer of complexity that may frustrate newer C++ programmers....
It's hardly trivial. The link goes to code that's already pretty complicated, and it's not enough to even make the standard containers work. For example, there's no operator<. Also, since it's not part of the language, it will be very difficult to make code that uses such a thing interoperate with code that doesn't.
佚名

We do, it's just not a constructor :-)

struct A {
  virtual ~A() {}
  virtual A * Clone() { return new A; }
};

struct B : public A {
  virtual A * Clone() { return new B; }
};

int main() {

   A * a1 = new B;
   A * a2 = a1->Clone();    // virtual construction
   delete a2;
   delete a1;
}

From this link: docwiki.embarcadero.com/RADStudio/XE4/en/… A use case, see: virtual __fastcall TYesNoDialog(TComponent *Owner);
M
Marius

Semantic reasons aside, there is no vtable until after the object is constructed, thus making a virtual designation useless.


Wrong. vtables are static and constant. They exist since the loading of the code and static data of the executable.
Correct, they are defined static and constant, but just not allocated and set up.
They are setup at program startup.
@Rich No. Virtual function work in constructors exactly as anywhere else. Virtual function calls are always based on the dynamic type of the object.
@Rich No: inside the base class ctor, a virtual call in a constructor will dynamically call the base class version, based on the dynamic type at the time: the base class. The virtual calls on the object under construction work the same whether they are in the ctor body or in any other function call by the ctor. The dynamic type of a base class subobject changes as construction of the derived class starts. You can only see that by printing typeid(*this).name().
U
UpAndAdam

Virtual functions in C++ are an implementation of run-time polymorphism, and they will do function overriding. Generally the virtual keyword is used in C++ when you need dynamic behavior. It will work only when object exists. Whereas constructors are used to create the objects. Constructors will be called at the time of object creation.

So if you create the constructor as virtual, as per the virtual keyword definition, it should have existing object to use, but constructor is used to to create the object, so this case will never exist. So you should not use the constructor as virtual.

So, if we try to declare virtual constructor compiler throw an Error:

Constructors cannot be declared virtual


K
Kushan Mehta

You can find an example and the technical reason to why it is not allowed in @stefan 's answer. Now a logical answer to this question according to me is:

The major use of virtual keyword is to enable polymorphic behaviour when we don't know what type of the object the base class pointer will point to.

But think of this is more primitive way, for using virtual functionality you will require a pointer. And what does a pointer require? An object to point to! (considering case for correct execution of the program)

So, we basically require an object that already exists somewhere in the memory (we are not concerned with how the memory was allocated, it may be at compile time or either runtime) so that our pointer can correctly point to that object.

Now, think of the situation about the moment when the object of the class to be pointed is being assigned some memory -> Its constructor will be called automatically at that instance itself!

So we can see that we don't actually need to worry about the constructor being virtual, because in any of the cases you wish to use a polymorphic behaviour our constructor would have already been executed making our object ready for usage!


1
1800 INFORMATION

When people ask a question like this, I like to think to myself "what would happen if this were actually possible?" I don't really know what this would mean, but I guess it would have something to do with being able to override the constructor implementation based on the dynamic type of the object being created.

I see a number of potential problems with this. For one thing, the derived class will not be fully constructed at the time the virtual constructor is called, so there are potential issues with the implementation.

Secondly, what would happen in the case of multiple inheritance? Your virtual constructor would be called multiple times presumably, you would then need to have some way of know which one was being called.

Thirdly, generally speaking at the time of construction, the object does not have the virtual table fully constructed, this means it would require a large change to the language specification to allow for the fact that the dynamic type of the object would be known at construction time. This would then allow the base class constructor to maybe call other virtual functions at construction time, with a not fully constructed dynamic class type.

Finally, as someone else has pointed out you can implement a kind of virtual constructor using static "create" or "init" type functions that basically do the same thing as a virtual constructor would do.


S
Shraddha Sinha

Although the concept of virtual constructors does not fit in well since object type is pre-requisite for object creation, its not completly over-ruled.

GOF's 'factory method' design pattern makes use of the 'concept' of virtual constructor, which is handly in certain design situations.


s
skrtbhtngr

Virtual functions are used in order to invoke functions based on the type of object pointed to by the pointer, and not the type of pointer itself. But a constructor is not "invoked". It is called only once when an object is declared. So, a constructor cannot be made virtual in C++.


so, why destructor can have virtual?
Quick search will yield the answer: stackoverflow.com/questions/461203/…
j
justin king

Interview answer is : virtual ptr and table are related to objects but not the class.hence constructor builds the virtual table hence we cant have virtual constructor as there is no Vtable before obj creation.


E
Edouard A.

You shouldn't call virtual function within your constructor either. See : http://www.artima.com/cppsource/nevercall.html

In addition I'm not sure that you really need a virtual constructor. You can achieve polymorphic construction without it: you can write a function that will construct your object according to the needed parameters.


N
Navneet Agarwal

A virtual-table(vtable) is made for each Class having one or more 'virtual-functions'. Whenever an Object is created of such class, it contains a 'virtual-pointer' which points to the base of corresponding vtable. Whenever there is a virtual function call, the vtable is used to resolve to the function address. Constructor can not be virtual, because when constructor of a class is executed there is no vtable in the memory, means no virtual pointer defined yet. Hence the constructor should always be non-virtual.


T
Tunvir Rahman Tusher

C++ virtual constructor is not possible.For example you can not mark a constructor as virtual.Try this code

#include<iostream.h>
using namespace std;
class aClass
{
    public:
        virtual aClass()
        {   
        }  
};
int main()
{
    aClass a; 
}

It causes an error.This code is trying to declare a constructor as virtual. Now let us try to understand why we use virtual keyword. Virtual keyword is used to provide run time polymorphism. For example try this code.

#include<iostream.h>
using namespace std;
class aClass
{
    public:
        aClass()
        {
            cout<<"aClass contructor\n";
        }
        ~aClass()
        {
            cout<<"aClass destructor\n";
        }

};
class anotherClass:public aClass
{

    public:
        anotherClass()
        {
            cout<<"anotherClass Constructor\n";
        }
        ~anotherClass()
        {
            cout<<"anotherClass destructor\n";
        }

};
int main()
{
    aClass* a;
    a=new anotherClass;
    delete a;   
    getchar(); 
}

In main a=new anotherClass; allocates a memory for anotherClass in a pointer a declared as type of aClass.This causes both the constructor (In aClass and anotherClass) to call automatically.So we do not need to mark constructor as virtual.Because when an object is created it must follow the chain of creation (i.e first the base and then the derived classes). But when we try to delete a delete a; it causes to call only the base destructor.So we have to handle the destructor using virtual keyword. So virtual constructor is not possible but virtual destructor is.Thanks


For virtual destructor try this link.stackoverflow.com/questions/461203/… might help
u
user3004790

Cant we simply say it like.. We cannot inherit constructors. So there is no point declaring them virtual because the virtual provides polymorphism .


R
Rich

The virtual mechanism only works when you have a based class pointer to a derived class object. Construction has it's own rules for the calling of base class constructors, basically base class to derived. How could a virtual constructor be useful or called? I don't know what other languages do, but I can't see how a virtual constructor could be useful or even implemented. Construction needs to have taken place for the virtual mechanism to make any sense and construction also needs to have taken place for the vtable structures to have been created which provides the mechanics of the polymorphic behaviour.


If we use a base class pointer to point to the base class object and call a virtual function using it. Then it would be late binding. But, will that be a run time polymorphism?
u
user3726672

There's a very basic reason: Constructors are effectively static functions, and in C++ no static function can be virtual.

If you have much experience with C++, you know all about the difference between static & member functions. Static functions are associated with the CLASS, not the objects (instances), so they don't see a "this" pointer. Only member functions can be virtual, because the vtable- the hidden table of function pointers that makes 'virtual' work- is really a data member of each object.

Now, what is the constructor's job? It is in the name- a "T" constructor initializes T objects as they're allocated. This automatically precludes it being a member function! An object has to EXIST before it has a "this" pointer and thus a vtable. That means that even if the language treated constructors as ordinary functions (it doesn't, for related reasons I won't get into), they'd have to be static member functions.

A great way to see this is to look at the "Factory" pattern, especially factory functions. They do what you're after, and you'll notice that if class T has a factory method, it is ALWAYS STATIC. It has to be.


Constructors are not static, period.
This is obvious nonsense. A f (g); invokes a copy constructor. And there's an object it could be a member function of, g. Or void foo (A a); ... foo(f);. Here, we need to construct a new A to call foo, and look there's an object it could be a member function of -- f.
Constructors are not static, to get a static constructor we have to initialize static data members independently.
s
shobhit2905

If you think logically about how constructors work and what the meaning/usage of a virtual function is in C++ then you will realise that a virtual constructor would be meaningless in C++. Declaring something virtual in C++ means that it can be overridden by a sub-class of the current class, however the constructor is called when the objected is created, at that time you cannot be creating a sub-class of the class, you must be creating the class so there would never be any need to declare a constructor virtual.

And another reason is, the constructors have the same name as its class name and if we declare constructor as virtual, then it should be redefined in its derived class with the same name, but you can not have the same name of two classes. So it is not possible to have a virtual constructor.


Constructor don't have a name. They have a specific syntax which uses the name of the class.
"the constructors have the same name as its class name and if we declare constructor as virtual, then it should be redefined in its derived class with the same name, but you can not have the same name of two classes. So it is not possible to have a virtual constructor." This is completely wrong. If that is the same case, how destructors can be virtual? We are not redefining the base destructor in derived class.
a
ajaysinghnegi

When a constructor is invoked, although there is no object created till that point, we still know the kind of object that is gonna be created because the specific constructor of the class to which the object belongs to has already been called. Virtual keyword associated with a function means the function of a particular object type is gonna be called. So, my thinking says that there is no need to make the virtual constructor because already the desired constructor whose object is gonna be created has been invoked and making constructor virtual is just a redundant thing to do because the object-specific constructor has already been invoked and this is same as calling class-specific function which is achieved through the virtual keyword. Although the inner implementation won’t allow virtual constructor for vptr and vtable related reasons.

Another reason is that C++ is a statically typed language and we need to know the type of a variable at compile-time. The compiler must be aware of the class type to create the object. The type of object to be created is a compile-time decision. If we make the constructor virtual then it means that we don’t need to know the type of the object at compile-time(that’s what virtual function provide. We don’t need to know the actual object and just need the base pointer to point an actual object call the pointed object’s virtual functions without knowing the type of the object) and if we don’t know the type of the object at compile time then it is against the statically typed languages. And hence, run-time polymorphism cannot be achieved. Hence, Constructor won’t be called without knowing the type of the object at compile-time. And so the idea of making a virtual constructor fails.


s
setller

"A constructor can not be virtual"

there are some valid reasons that justify this statement.

to create an object the constructor of the object class must be of the same type as the class. But, this is not possible with a virtually implemented constructor. at the time of calling the constructor, the virtual table would not have been created to resolve any virtual function calls. Thus, a virtual constructor itself would not have anywhere to look up to.

As a result, it is not possible to declare a constructor to be virtual.


r
ravi chandra

The Vpointer is created at the time of object creation. vpointer wont exists before object creation. so there is no point of making the constructor as virtual.


The vptr is an implementation detail; it implements the concept of dynamic type. The ctor give a dynamic type, creates a polymorphic object.