I have a container class to which i can send a Geometry object as constructor argument.
Geometry is a polymorphic class as interface for other geometric types like Sphere and Rectangle.
My question is that in Container class the constructor with arguments "Container(std::string str, Geometry* geometry)" can i code this in more flexible manner.
Whenever i will add a new SubClass to Geometry than i would need to write another IF condtion in Container class Constructor.
include "pch.h"
#include <iostream>
#include<fstream>
#include "Container.h"
#include "Geometry.h"
#include "Sphere.h"
#include "Rectangle.h"
#include "Container.h"
int main()
{
const char* fileName = "saved.txt";
Sphere sph;
Rectangle rect;
Container contSphere("ABC", &sph);
Container contRectangle("DEF", &rect);
Sphere* s = (Sphere*)contSphere.getGeomtry();
s->PrintGeom();
Rectangle* r = (Rectangle*)contRectangle.getGeomtry();
r->PrintGeom();
do
{
std::cout << '\n' << "Press a key to continue...";
} while (std::cin.get() != '\n');
}
///////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <string>
class Geometry
{
private:
std::string stdstringGeom;
std::string stdstrType;
public:
Geometry() : stdstringGeom("GeometyrString"), stdstrType("Geometry") {}
virtual ~Geometry() {}
virtual std::string getType()
{
return stdstrType;
}
virtual void PrintGeom()
{
std::cout << "geometry virtual function";
}
};
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "Geometry.h"
class Sphere : public Geometry
{
private:
std::string stdstrSphere;
std::string stdstrType;
public:
Sphere() : Geometry() , stdstrSphere( "DefaultSphere") , stdstrType("Sphere") {}
Sphere( std::string str) : Geometry() , stdstrSphere(str) , stdstrType("Sphere"){}
void PrintGeom()
{
std::cout << "Sphere Virtual Function" << std::endl;
}
std::string getType()
{
return stdstrType;
}
};
///////////////// Defination for Constructor class////////////////////
#include "Geometry.h"
#include "Sphere.h"
#include "Rectangle.h"
class Container
{
private:
std::string stdstrCont;
Geometry* geom;
public:
Container() : stdstrCont("NoName") { geom = new Geometry; }
Container(std::string str, Geometry* geometry) : stdstrCont(str)
{
// I am doing this to avoid slicing and i want to do a deep copy.
if (geometry->getType() == "Sphere")
{
Sphere* sph = (Sphere*)geometry;
geom = new Sphere(*sph);
}
else if (geometry->getType() == "Rectangle")
{
Rectangle* rec = (Rectangle*)geometry;
geom = new Rectangle(*rec);
}
}
~Container()
{
if (geom != nullptr)
delete geom;
}
Geometry* getGeomtry()
{
return geom;
}
void PrintContainer()
{
std::cout << stdstrCont;
}
};
Your design is all backward, and a consequence is that you are making the Container responsible for working out the type of all Geometry objects passed to it, in order to copy them. That will make your Container a maintenance nightmare - if someone creates another class derived from Geometry, they can forget to modify Container accordingly.
You've also omitted code that is relevant to your question (like virtual destructors) and included code that is irrelevant to the question (declaration of std::string members, and initialisation of them in constructors, and other virtual functions).
Instead, it would be better to make the class Geometry, and its derived classes, responsible for copying themselves.
At heart would be the Geometry class itself
#include <memory> // for std::unique_ptr
class Geometry
{
public:
Geometry() {};
virtual ~Geometry() = default;
virtual std::unique_ptr<Geometry> Clone() const = 0;
};
(I've omitted the std::string members for convenience). The derived classes then override the Clone() function, viz;
class Sphere: public Geometry
{
public:
Sphere() : Geometry() {};
~Sphere() = default;
std::unique_ptr<Geometry> Clone() const {return std::unique_ptr<Geometry>(new Sphere(*this));};
};
// similarly for other shapes
The Clone() function is pure virtual in Geometry, so the derived classes cannot be instantiated unless you remember to override it.
The responsibility for cloning rests with Geometry and its derived classes - and the compiler will helpfully diagnose an error if a class is derived from Geometry that does not override the Clone() function.
Then, all a Container needs to do is have a member std::unique_ptr<Geometry> or (if you intend to have a set of them) a std::vector<std::unique_ptr<Geometry> >.
For the case where the Container only needs a single Geometry, the definition of Container might be
class Container
{
public:
Container() : geom() {};
Container(Geometry *p) : geom(p->Clone()) {};
Container(const Container &c) : geom(c.geom->Clone()) {};
Container &operator=(const Container &c)
{
geom = c.geom->Clone(); // this will release the existing c.geom
return *this;
};
~Container() = default;
private:
std::unique_ptr<Geometry> geom;
};
The reason I've used std::unique_ptr<Geometry> in the above (instead of Geometry * as in your code) is that std::unique_ptr<> avoids the need to explicitly decide when to destroy a Geometry object.
The no-argument constructor of Container initialises to containing a null Geometry (i.e. a null pointer).
The constructor of Container that accepts a Geometry * clones the passed object, and does not assume ownership of it. This means the caller is responsible for the lifetime of the object it passes. This is consistent with your main(), which constructs objects of automatic storage duration.
Note that I'm following the "rule of three" - if a non-default version of a copy constructor, copy assignment, or destructor is defined, then the other two should also be defined. The operator=() in the above works in a manner consistent with the copy constructor (i.e. it clones objects in the Container, rather than causing Geometry objects to be shared between Containers). The destructor is explicitly defined as the default, since the Container is not explicitly managing lifetime of its members (the destructor of std::unique_ptr does the work).
Related
I've been trying to create a factory method which allocates subclasses entities from a given abstract class, which I'll name Shape for simplicity. It looks something like this:
Shape* makeChild(Type type) const
{
switch(type)
{
case QUAD:
return new Quad();
case RECTANGLE:
return new Rectangle();
case TRIANGLE:
return new Triangle();
default:
return new Rectangle();
}
}
Now I'm trying to keep these entities inside a structure, and I understand I need to allocate Shape* entities, but I would like for the objects to be automatically managed by using std::unique_ptr<Shape> instead.
My ShapeTree struct looks something like this:
struct ShapeTree {
int index_;
std::vector<std::unique_ptr<Shape>> shapes_;
void add(Shape* shape) {shapes_.push_back(std::make_unique<Shape>(shape));}
void removeLast(){shapes_.pop_back();}
ShapeTree(const int index) : index_{index}{}
ShapeTree(const int index, std::vector<std::unique_ptr<Shape>>& shapes) : index_{index}, shapes_{std::move(shapes)}{}};
Compiler complains about having Shape default copy constructor being marked as deleted, I understand this is the case since I have a unique pointer and I can't copy it, but deleting the copy constructor and assignment and using the default move constructor and assignment won't work either. It also complains that no instances of Shape can be created as it is abstract, even thought I am only returning subclasses.
A different version of the same structure works completely fine when using raw pointers. E.g.
struct ShapeTree {
int index_;
std::vector<Shape*> shapes_;
void add(Shape* shape) {shapes_.push_back(shape);}
void removeLast(){shapes_.pop_back();}
ShapeTree(const int index) : index_{index}{}
ShapeTree(const int index, std::vector<Shape*>& shapes) : index_{index}, shapes_{std::move(shapes)}{}};
What am I doing wrong? How can i achieve the same result using unique_ptr?
The immediate cause of your error is this line:
void add(Shape* shape) {shapes_.push_back(std::make_unique<Shape>(shape));}
std::make_unique is used to create a new object to be managed by the unique_ptr.
In your case you already allocated your object with new, and therefore you should simply use the std::unique_ptr constructor.
An immediate solution would be:
//----------------------------------------vvvvvvvvvvvvvvv-----------------
void add(Shape* shape) {shapes_.push_back(std::unique_ptr<Shape>(shape));}
However:
A better solution will avoid using new altogether.
makeChild can return a std::unique_ptr which can be moved into the vector:
#include <vector>
#include <memory>
struct Shape {};
struct Rectangle : public Shape {};
// ... all the derived Shapes
std::unique_ptr<Shape> makeChild()
{
// Here you can create a std::unique_ptr to any derive from Shape based on a `Type` parameter you can add:
return std::make_unique<Rectangle>();
}
struct ShapeTree {
int index_;
std::vector<std::unique_ptr<Shape>> shapes_;
//---------------------------------------------------------vvvvvvvvv------
void add(std::unique_ptr<Shape> shape) { shapes_.push_back(std::move(shape)); }
void removeLast() { shapes_.pop_back(); }
// ...
};
int main()
{
ShapeTree st{ 333 };
st.add(makeChild());
}
Suppose we have the following class template:
template<typename T>
class Object
{
public:
Object() = default;
Object(const Object&) = delete;
Object(Object&& other) noexcept
{
if (this != &other)
{
static_cast<T*>(this)->Release();
m_Id = std::exchange(other.m_Id, 0);
}
}
auto operator=(const Object&) = delete;
Object& operator=(Object&& other) noexcept
{
if (this != &other) {
static_cast<T*>(this)->Release();
m_Id = std::exchange(other.m_Id, 0);
}
return *this;
}
~Object()
{
static_cast<T*>(this)->Release();
m_Id = 0;
}
protected:
std::uint32_t m_Id;
};
(Please ignore the duplication in the move constructor and move assignment operator for the moment)
This class is meant to act as a base class for OpenGL object wrappers. Following is an example use:
class VertexBuffer : public Object<VertexBuffer>
{
public:
VertexBuffer()
{
glGenBuffers(1, &m_Id);
...
}
void Release()
{
glDeleteBuffers(1, &m_Id);
}
};
The Object<T> class template is supposed to take care of the bookkeeping.
The reason for doing this is that the pattern in the Object<T> class is repeated the exact same way for (almost) every OpenGL object wrapper that might be written. The only difference is the creation and deletion of the objects which is handled by the constructor and the Release() function in this example.
Now the question is whether this (Object<T>::~Object() to be specific) taps into UB land? Undefined Behavior Sanitizer doesn't report any errors but I've never done this, so I though of asking people with more experience to make sure.
Short answer: Yes, this is undefined behaviour, don't do that.
Long answer:
The destruction of VertexBuffer invokes first ~VertexBuffer() and then invokes ~Object<VertexBuffer>() afterwards. When ~Object<VertexBuffer>() is invoked the VertexBuffer "part" of the object has already been destroyed, i.e. you are now doing an illegal downcast via static_cast (the remaining valid part of the object is a Object<VertexBuffer>, not a VertexBuffer).
And undefined behaviour permits the compiler to do ANYTHING - it might even (appear to) work, only to suddenly stop working (or only work when you build in Debug mode, but not when in Release). So, for your own sake, please don't do that.
Don't do that. That'll cause an undefined behavior.
Instead, implement the template class as a derived class, like the following example.
class BufferGrandBase {
protected:
GLuint id;
};
template<class B>
class Buffer : public B {
public:
Buffer() {
B::Create();
}
~Buffer() {
B::Destroy();
}
};
class VertexBufferBase : public BufferGrandBase {
public:
void Create() { glGenBuffers(1, &id); }
void Destroy() { glDeleteBuffers(1, &id); }
};
typedef Buffer<VertexBufferBase> VertexBuffer;
This pattern will also simplify implementing constructors and operators.
If you have a "thing" that holds an Object<T> where T is the Crtp-type, that "thing" is likely a template anyway.
So instead of holding an Object<T>, why don't you just hold a T, which is the full type that inherits from Object<T>. If that is destroyed it will call T::~T() automatically.
In addition, perhaps you want to do private or protected inheritance from Object<T> to discourage users from slicing the Crtp-type.
Edit: You can simplify your Ts by moving the actual work into Object<T>:
class VertexBuffer : public Object<VertexBuffer>
{
public:
VertexBuffer() : Object<VertextBuffer>(glGenBuffers, glDeleteBuffers, 1) {
... // more stuff you did in your original constructor
}
};
Where Object looks like this in addition to what you already have:
template <typename T>
class Object {
void (*release)(int, std::uint32_t*);
int i;
Object() = delete;
Object(void (*acquire)(int, std::uint32_t*), void (*release)(int, std::uint32_t*), int i = 1) : release{release}, i{i} {
acquire(i, &m_Id);
}
~Object() {
release(i, &m_Id);
}
// rest of your Object class
};
This is close to the model of std::unique_ptr<> with a custom deleter. But it doesn't quite fit because std::unique_ptr has to hold a pointer and this case needs an integer handle-type.
So here is a brief example. It is general good advice to prefer inclusion over inheritance so I have deliberately placed the helper object inside the owning class.
All I'm really trying to demonstrate here is that there are a number of ways to customise behaviours in templates beyond call members of instances.
#include <iostream>
#include <memory>
typedef size_t gd_size;
typedef int gd_handle;
void gen_buffers(gd_size size,gd_handle*buffs);
void del_buffers(gd_size size,gd_handle*buffs);
typedef void (*gd_func)(gd_size,gd_handle*buff);
template<gd_func gfunc,gd_func dfunc> class GenDel{
public:
GenDel(){gfunc(1,&buff);}
~GenDel(){dfunc(1,&buff);}
int get()const{return buff;}
private:
int buff;
GenDel(const GenDel&)=delete;
};
class BufferHolder{
public:
BufferHolder(){}
void do_thing() const{
std::cout<<"using "<<buffer.get()<<'\n';
}
private:
GenDel<gen_buffers,del_buffers> buffer;
};
int main() {
BufferHolder b;
BufferHolder c;
b.do_thing();
return 0;
}
int seed{0};
void gen_buffers(gd_size size,gd_handle*buffs){
for(size_t i{0};i<size;++i){
buffs[i]=++seed;
std::cout << "generated "<< buffs[i] << '\n';
}
}
void del_buffers(gd_size size,gd_handle*buffs){
for(gd_size i{0};i<size;++i){
std::cout << "deleted "<< buffs[i] << '\n';
}
}
I have multiple child classes inside a parent class vector where each child has it's own type. The parent has a virtual getType function and each child overrides it with it's own; not even sure if I need this TBH but I got from this Access child members within parent class, C++
When I loop over the vector (loop not shown here), the type is only that of the parent, since it's a vector of Parents, but I need the type of each individual child made with it's own constructor.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Parent
{
private:
string type = "parent";
public:
virtual string getType()
{
return type;
}
};
class Child1 : public Parent
{
string type = "type1";
public:
string getType()
{
return type;
}
};
class Child2 : public Parent
{
string type = "type2";
public:
string getType()
{
return type;
}
};
//main.cpp
int main()
{
vector<Parent> children;
Child1 t1;
Child2 t2;
children.push_back(t1);
children.push_back(t2);
//THIS WORKS
cout << t1.getType(); // returns type1
// I NEED THIS TO WORK
cout << children[0].getType(); // returns parent.
cout << children[1].getType(); // I need type1 && type2
}
How can I do this? I have no way of knowing what type of child each is otherwise, or is there another way to do this?
You just experimented slicing.
A Child is a Parent plus a few more things.
When you try to put a Child in the vector of Parent, only the Parent part of each of these Children is put in the vector (because the vector does not contain Children but Parents); hence the name slicing.
In order to obtain the dynamic polymorphism you are looking for, you need a vector of pointers to Parent; this way, each pointed-to element can be whether a Parent or a Child and behave accordingly.
This is often done with a dynamic allocation of each element in the vector, but this is not mandatory. For example, you could store all the Parents in a vector, all the Children 1 in another, and so on, and finally use a vector of pointers to designate some of them in any order.
If you decide to allocate each Parent/Child individually, you should consider smart-pointers like std::unique_ptr<T> rather than raw pointers and new/delete.
You will find below your example slightly modified in order to obtain dynamic polymorphism.
It relies on dynamic allocation of each element thanks to std::unique_ptr<T>/std::make_unique().
Note that, because of dynamic polymorphism, you need a virtual destructor (even if it does nothing special).
Since this hierarchy of types is intended for dynamic polymorphism, it is encouraged to prevent slicing (that you have just experienced) by forbidding the use of copy/move operations.
Thus, you have to provide one or several constructors that fulfil your needs (but this is quite common).
My last advice is « avoid dynamic polymorphism; prefer template » but it is another topic ;^)
/**
g++ -std=c++17 -o prog_cpp prog_cpp.cpp \
-pedantic -Wall -Wextra -Wconversion -Wno-sign-conversion \
-g -O0 -UNDEBUG -fsanitize=address,undefined
**/
#include <iostream>
#include <string>
#include <vector>
#include <memory> // std::unique_ptr<T>, std::make_unique()
class Parent
{
public:
virtual ~Parent() =default; // ensure correct destruction
// forbid copy and move in order to prevent slicing
Parent(const Parent &) =delete;
Parent &operator=(const Parent &) =delete;
Parent(Parent &&) =delete;
Parent &operator=(Parent &&) =delete;
Parent() =default; // provide a suitable constructor
virtual
const std::string &
getType() const
{
return type;
}
private:
// inline static // is probably better
const std::string type{"parent"};
};
class Child1: public Parent
{
public:
const std::string &
getType() const override
{
return type;
}
private:
// inline static // is probably better
const std::string type{"type1"};
};
class Child2 : public Parent
{
public:
const std::string &
getType() const override
{
return type;
}
private:
// inline static // is probably better
const std::string type{"type2"};
};
int
main()
{
const auto p=Parent{};
std::cout << "p: " << p.getType() << '\n';
const auto c1=Child1{};
std::cout << "c1: " << c1.getType() << '\n';
const auto c2=Child2{};
std::cout << "c2: " << c2.getType() << '\n';
auto people=std::vector<std::unique_ptr<Parent>>{};
for(auto i=0; i<2; ++i)
{
people.emplace_back(std::make_unique<Parent>());
people.emplace_back(std::make_unique<Child1>());
people.emplace_back(std::make_unique<Child2>());
}
for(const auto &e: people)
{
std::cout << e->getType() << '\n';
}
return 0;
}
How and where should the objects created by returnShapeType be deleted?
This is a factory method demonstration program.
Please show the code.
class Shape
{
public:
Shape() {}
virtual void print() {std::cout << "\nFrom shape print";}
};
class Triangle: public Shape
{
public:
Triangle(){}
virtual void print() {std::cout << "\nFrom triangle print";}
};
class Rectangle: public Shape
{
public:
Rectangle(){}
virtual void print() {std::cout << "\nFrom rect print";}
};
class CreateShapeObject
{
public:
CreateShapeObject() {}
Shape *returnShapeType( std::string arg )
{
if (arg == "Triangle")
return new Triangle;
else if (arg == "Rectangle")
return new Rectangle;
}
};
////////////
class EndDeveloper
{
public:
CreateShapeObject obj;
EndDeveloper()
{
Shape *p = obj.returnShapeType("Triangle");
p->print();
Shape *q = obj.returnShapeType("Rectangle");
q->print();
}
};
Using raw pointers is error prone. Use a unique_ptr:
std::unique_ptr<Shape> returnShapeType(const std::string& arg)
{
if (arg == "Triangle")
return std::make_unique<Triangle>();
else if (arg == "Rectangle")
return std::make_unique<Rectangle>();
throw std::invalid_argument("Invalid shape");
}
You can use it conveniently with auto:
auto shape = obj.returnShapeType("Triangle");
unique_ptr can be also implicitly converted to shared_ptr:
std::shared_ptr<Shape> shape = obj.returnShapeType("Triangle");
You have to establish ownership principles in your design.
In your posted code, CreateShapeObject does not retain a pointer to the object that was constructed. It simply returns a pointer to the constructed object. This implies the calling function/class must take ownership of the object. They ought to be responsible for deleting it unless they pass the ownership to another function/class in which case the other function/class ought to be responsible for deleting it.
If you want to make CreateShapeObject responsible for deleting the objects it constructs, you'll have to update it to keep track of the objects it constructs. At that point, you may want to change the name of the class to reflect the dual responsibility. Something along the lines of ShapeObjectManager will make more sense.
Treat any use of new via the factory like you would treat any other use of new.
I.e. the code/class which uses new (via factory or not) is responsible for doing the delete, too.
I have several similar classes inheriting from the same Base-Class/Interface (Base class 1), and they share a couple similar functions, but then also have their own distinct functions. They all also have their own member variables of different classes, and each of those inherits from the same Base-Class/Interface (Base class 2). Is it possible to define a variable in Base class 1, of type Base class 2, then in the actual implementation of classes using Base class 1, have the variable of type Base class 2 be its proper type. Kinda hard to explain, so simplified example below.
//Base-Class 1
class Shape
{
public Shape() {}
ShapeExtra m_var;
//The common functions
public GetVar(){ return m_var; }
}
class Circle : Shape
{
public Circle() { m_var = new CircleExtra(); }
public void CircleFunc()
{
m_var.CircleExtraFunc();
}
}
class Triangle : Shape
{
public Triangle() { m_var = new TriangleExtra(); }
public void TriangleFunc()
{
m_var.TriangleExtraFunc();
}
}
.
.
.
//Base_Class 2
class ShapeExtra
{
public ShapeExtra() {}
}
class CircleExtra : ExtraClass
{
public CircleExtra() {}
void CircleExtraFunc() {//Do stuff}
}
class TriangleExtra : ExtraClass
{
public TriangleExtra() {}
void TriangleExtra() {//Do stuff}
}
.
.
.
So, I need the m_var in the child classes to be kept it as its own unique version. Because right now (w/o the extra CircleExtra m_var;), the GetVar() works, but in CircleFunc, m_var is still type of ShapeExtra, and thus doesn't know that CircleExtraFunc exists. I could cast m_var each time I wanted to do that, but that is repetitive and not worth it in my real-world case. Is there a way to utilize the functions in unique classes based off of ShapeExtra, while keeping the GetVar() function in Shape?
Please ask questions if there is anything I left out.
Simply with inheritance and without using pointers it is not possible, as C++ is a statically-and-strictly-typed language.
You can inherit both the variable and the function, but you'll need to cast function return value.
You can also override the function to make it return the concrete type, but then you have to cast the variable inside the function.
You can also declare the same var with the concrete class in subclasses, but then you just hide the variable in the superclass and inherit nothing.
I'd rather go for a solution using templates. Make the type of the variable a template type and extend the template using a concrete type in subclasses. It'll work perfectly.
It's been a long time since I last programmed in C++ and I beg your pardon if there are errors in the following example. I'm sure you can easily make it work.
template <class S>
class Shape {
S m_var;
//......
public:
S var () {
return m_var;
}
//.......
}
class Circle: Shape <CircleExtra> {
// var method returns CircleExtra
//......
}
Edit:
Regarding some comment, to allow virtual invocation of the method, it is possible to use correlated return types. Something like the following example.
class Shape {
public:
virtual ShapeExtra *var () = 0;
}
template <typename SE>
class ConcreteShape: Shape {
public:
virtual SE *var() {
return &m_var;
}
// Constructor, etc.
private:
SE m_var;
}
Or some variation. Now concrete shapes can benefit from extending the template, as long as SE * is correlated with ShapeExtra * (the type parameter extends ShapeExtra). And you can vall the method transparently through Shape interface.
Using pointers, this is totally possible.
Using your example, you could do something like this:
#include <iostream>
#include <memory>
using namespace std;
//Extras
class ShapeExtra
{
public:
ShapeExtra() {}
void ShapeFunc() { std::cout << "Shape"; }
virtual ~ShapeExtra() = default; //Important!
};
class Shape
{
public:
std::unique_ptr<ShapeExtra> m_var;
//require a pointer on construction
//make sure to document, that Shape class takes ownership and handles deletion
Shape(ShapeExtra* p):m_var(p){}
//The common functions
ShapeExtra& GetVar(){ return *m_var; }
void ShapeFunc() {m_var->ShapeFunc();}
};
class CircleExtra : public ShapeExtra
{
public:
void CircleExtraFunc() {std::cout << "Circle";}
};
class Circle : public Shape
{
CircleExtra* m_var;
public:
Circle() : Shape(new CircleExtra()) {
m_var = static_cast<CircleExtra*>(Shape::m_var.get());
}
void CircleFunc()
{
m_var->CircleExtraFunc();
}
};
int main() {
Circle c;
//use the ShapeExtra Object
c.GetVar().ShapeFunc();
//call via forwarded function
c.ShapeFunc();
//call the circleExtra Function
c.CircleFunc();
return 0;
}
Test it on ideone
Note the use of pointers and a virtual destructor:
By using a virtual destructor in the ShapeExtra base class, you make it possible to destruct an object of any derived class, using a ShapeExtra*. This is important, because
by using a std::unique_ptr<ShapeExtra> instead of a plain C-pointer, we make sure that the object is properly deleted on destruction of Shape.
It is probably a good idea to document this behaviour, i.e. that Shape takes the ownership of the ShapeExtra*. Which especially means, that we do not delete CirleExtra* in the Circle destructor
I decided here to require the ShapeExtra* on construction, but its also possible to just use std::unique_ptr::reset() later and check for nullptr on dereferencing Shape::m_var
Construction order is this: On calling the constructor of Circle, we first create a new CircleExtra which we pass to Shape before finally the constructor of Circle is executed.
Destruction order is Circle first (was created last), then Shape which also destructs the ShapeExtra for us, including (via virtual function) the CircleExtra
I would recommend the following approach:
class ShapeExtra
{
public:
virtual ~ShapeExtra() { }
virtual void SomeCommonShapeFunc() { std::cout << "Shape"; }
};
class Shape
{
public:
virtual ShapeExtra &GetVar() = 0; // Accessor function.
};
Note that the class Shape does not have any data members at all. After that for each derived class you need:
class CircleExtra : public ShapeExtra
{
public:
void SomeCommonShapeFunc() { std::cout << "Circle"; }
};
class Circle : public Shape
{
CircleExtra m_var; // Data member with circle specific class.
public:
virtual ShapeExtra &GetVar() { return m_var; }
};
Implementation of virtual method in Circle will return reference to the base class ShapeExtra. This will allow using this extra in the base class.
Note that pointers and templates are not used at all. This simplifies the overall design.