2

I went through various blogs but nowhere I can find the reason of having virtual constructors in C++.

Why is virtual constructor needed and lets say if we go through the wrong way of creating virtual constructor how would our code look like and what would be the problem with it? And how does the factory method helps us in rectifying that?

Can someone provide me the wrong way and then the correct way of doing it using factory method?

EDITED: Discussion in comment, let me know if my understanding is correct

Factory Design Pattern helps us solve the problem of dynamic object creation while using polymorphism. Below is wrong code, but lets say if C++ were to have virtual constructors it would help us solve the same problem by making the base class return the object of derived class.

class Base
{
    public:
    Base() { }
    someWayTOReturnDerivedCLassType createObject()
    {
        return new super(); // if virtual constructor was possible Derived class constructor would have been called here
    }
}

class Derived: public Base
{
    public:
    Derived() { }
}

Since C++ does not have any way to do above, that is the first and forecast reason we cannot have virtual constructor in c++.

Kilian Foth
  • 107,706
  • 45
  • 295
  • 310
H Kumar
  • 31
  • 2
  • 2
    Are you sure that [virtual constructors are a thing?](https://www.tutorialspoint.com/virtual-constructor-in-cplusplus#:~:text=In%20C%2B%2B%2C%20the%20constructor,should%20always%20be%20non%2Dvirtual.) – Robert Harvey Jul 07 '23 at 19:17
  • Anyway, a factory method is just that: a method that creates objects. Has nothing to do with "virtual constructors." – Robert Harvey Jul 07 '23 at 19:18
  • 4
    @RobertHarvey - In Go4's Design Patterns book, it's stated that "Virtual Constructor" is a different name for the Factory Method pattern, where you inherit from an abstraction that exposes (possibly only to derivatives) an abstract factory method (that it itself may use), and you override it. Maybe that's what the OP is asking about. – Filip Milovanović Jul 07 '23 at 20:24
  • 1
    @FilipMilovanović if that’s what this is about then the answer is when you want to build a thingy that does some whatever without having know which whatever. You want to be handed something that knows so you don’t have to. – candied_orange Jul 07 '23 at 23:56
  • @candied_orange - yeah, an example might be a GUI framework that needs to, as part of its own logic, instantiate some widget (like a fully custom context menu) that you, the *user* of the framework, are yet to write at some point in the future. The framework designers need to be able to write code that instantiates that widget without knowing what that widget even is (because it doesn't even exist yet), so they provide an abstraction, and let you override a "creator" method. – Filip Milovanović Jul 08 '23 at 00:24
  • @FilipMilovanović yes that's exactly what is confusing me, lets say if virtual constructor was there in the first place what problems would it help us solve. And how factory design pattern helps us solve that issue. – H Kumar Jul 08 '23 at 07:50
  • Hey all, Please check my edited question(bottom). – H Kumar Jul 08 '23 at 07:51

3 Answers3

3

The real question is what you want to achieve, and either achieve it in C++, or in another language if you think it would suit the needs better.

Why can't virtual constructors exist in C++?

Imagine one second that it would exist and that your Base could have a virtual constructor.

Let's keep thing simple, and do not even consider derived classes that need additional arguments in the constructor (like Shape() and Circle(center,radius)) nor more complex cases with multiple inheritance and virtual inheritance.

Imagine that in your Derived class you'd have a member function f() that would invoke createObject(). Now you define a class DerivedDerived : public Derived. And imagine that there is a function g() in that class that invokes f(). Two possible semantics:

  • createObject() creates an object of the class that invokes it. In this case it would create a Derived when called via g(). This semantic would fail for polymorphic abstract class that would invoke it, e.g. if Derived was abstract.
  • createObject() creates always an object of the most derived class. But this would require at compile time to know all potential derived classes, or have at runtime additional code everytime you'd create an object. And here we'd be back with the multiple inheritance issue. And most of all, this is not in line with the C++ principle that you should not pay for something you don't need.

Now this is not the only issue. The semantics of C++ is that during the constructor the Base subobject of Derived the object is a Base and doesn't know about Derived until its construction is finished.

In other words, virtual constructors would conflict with fundamental semantics and assumptions of billions of lines of source code around the globe, just for a few exceptional cases where it could be useful.

How to solve it

As you figured out, the factory pattern could solve a number of use cases. Unfortunately, not exactly yours.

But there's an allost perfect match for your need: a variant of the prototype pattern, which promotes polymorphism, by making sure that classes that need it implement a virtual clone() function that creates a copy of itself. All you need is to have a virtual createObject() that only create an object of the same kind instead of cloning it.

Of course this requires some boilerplate code in each class of your inheritance network, but you could extremely well adapt semantics to your needs. Possibly some templating techniques could alleviate this task, but this would be a candidate for a SO question ;-)

Christophe
  • 74,672
  • 10
  • 115
  • 187
1

In OO programming, you have a factory in order to construct objects - it's really that simple.

Most languages have a "new" keyword, which is a shortcut for a compiler-defined static method which allocates a certain amount of memory on the heap and runs through a construction method for the new object instance (a fundamental method which wires up the object v-table, in addition to any programmer-supplied construction code).

To perform this outside the scope where all the relevant internal parameters for the object are available (such as what size of memory needs to be allocated for its public and private fields, plus it's v-table), and if you aren't to expose all the relevant internal parameters (which would be contrary to OO tenets that you don't even acknowledge the existence of things like private fields, outside the object itself), then you have to expose a construction method.

This external construction can be done as simply as supplying a function pointer for a constructor method, but in OO programming it's a tenet that you don't supply raw function pointers, you supply objects - that object which carries the necessary construction function pointer is called a "factory".

Other more complicated tricks can be achieved with factories, but this is the most essential reason they exist - they exist as a carrier for the method that constructs objects.

Steve
  • 6,998
  • 1
  • 14
  • 24
-1

You have situations where you want an instance of a class, but you don’t care exactly which class. Using a C++ constructor, you have to specify the class. and you will get an instance of that class, and nothing else.

With a factory, you tell the factory what you want, and it decides what kind of instance of which class it will construct, so different calls can give you instances of different classes, all usable with the same interface obviously.

You could achieve the same by having a static method in your base class. But the factory is considered better style.

MacOS often does this hidden and behind the scenes, for example an array class and a class for arrays with zero elements which is a singleton subclass. You are not bothered about this, just an optimisation, so it happens within the array class.

gnasher729
  • 42,090
  • 4
  • 59
  • 119