I have an abstract class Engine3D and it’s structures (Vector3D, etc.) in the header files.
Now, I have an implementation for that class, ConcreteEngine3D : Engine3D. Also, I have other classes like ConcreteVector3D : Vector3D that have additional members and methods that will be used inside ConcreteEngine3D (for the sake of this example, let’s say it’s float length and calculateLength()).
In main.cpp I have the code:
#include "ConcreteEngine3D.h"
Engine3D * engine;
...
int main(){
engine = new ConcreteEngine3D();
Vector3D* vector = new Vector3D(engine, 10, 5, 2);
}
I want the variable vector be of type ConcreteVector3D*.
I will need that type in ConcreteEngine3D, but in main.cpp I shouldn’t even know it’s that type and don’t have to use extended fields like length. Also, I can’t use in main.cpp anything specifically from ConcreteEngine3D.h (only Engine3D.h) – it’s for the flexibly, changing the implementation must means only changing the inclusion and line with new ConcreteEngine3D().
I do not want to modify that code above or original headers from Engine3D.
In the constructor of Vector3D I always put a pointer to Engine3D object (and I give here ConcreteEngine3D type).
Maybe can I do something in the constructor of Vector3D to change the type of it?
For example call Vector3D* Engine3D::convert(Vector3D v) inside of the constructor which will be inherited from Engine3D in ConcreteEngine3D (which creates a new ConcreteVector3D object with fields from Vector3D and returns it).
Of course that code doesn’t work:
Vector3D::Vector3D(Engine3D *engine){
//how to 'return' or 'convert' the type to the one that returns engine->convert(this);
}
So basically, I want to get the effect of code below but without the line vector = engine->convert(vector) or Vector3D* vector2 = new ConcreteVector3D(engine, 10, 5, 2).
#include "ConcreteEngine3D.h"
Engine3D * engine;
...
int main(){
engine = new ConcreteEngine3D();
Vector3D* vector = new Vector3D(engine, 10, 5, 2); //produces Vector3D, not ConcreteVector3D
vector = engine->convert(vector); //cannot be here! but creates the right object
Vector3D* vector2 = new ConcreteVector3D(engine, 10, 5, 2); //also creates rights object, but cannot be here!
}
Also, I don’t want to use factory in Engine3D or ConcreteEngine3D. I want to allow the ‘user’ create Vector3D just the way I have written in the first code.
It sounds like you would want to use abstract factory pattern to instantiate your objects so that you would not have to directly call constructors of the concrete classes. Then, in case you would want to change the concrete types that implement your interfaces, you would only need to either link in a different implementation of your abstracy factory, or select a proper factory implementation at run time.
Edit: Missed the “don’t want to use factory”… Anyway you will need some kind of redirection, because constructor will return the type you instantiate. Closest you can get is probably creating a static factory method “create” to class Vector3D that returns a pointer to Vector3D, but internally creates an instance of concrete implementation class. In case you do that, it is good practice to make the constructor of Vector3D private to prevent creating the vector in “wrong way”.