Instantiating a class with virtual methods without a heap allocation - c++

class Base
{
public:
virtual ~Base() {}
virtual void Foo() = 0;
};
class FirstDerived: public Base
{
public:
void Foo() { cout << "FirstDerived" << endl; }
};
class SecondDerived: public Base
{
public:
void Foo() { cout << "SecondDerived" << endl; }
};
union PreallocatedStorage
{
PreallocatedStorage() {}
~PreallocatedStorage() {}
FirstDerived First;
SecondDerived Second;
};
class ContainingObject
{
public:
Base* GetObject()
{
if (!m_ptr)
{
// TODO: Make runtime decision on which implementation to instantiate.
m_ptr = new(&m_storage) SecondDerived();
}
return m_ptr;
}
~ContainingObject()
{
if (m_ptr)
{
m_ptr->~Base();
}
}
private:
PreallocatedStorage m_storage;
Base* m_ptr = nullptr;
};
int main()
{
auto object = make_unique<ContainingObject>();
// ...
// Later, at a point where I don't want to make more heap allocations...
// ...
auto baseObject = object->GetObject();
baseObject->Foo();
return 0;
}
What I'm trying to achieve here:
I need to instantiate a class that has virtual methods.
At the point in time I know exactly which derived class to instantiate, I cannot make further heap allocations (this is just out of curiosity, so the exact reason why is not relevant).
Hence, I want to somehow pre-allocate enough space to hold any possible implementation, and then decide later what class I'm going to instantiate in it.
Is there anything standards-non-compliant/undefined behavior in the above code?

The code is correct. See the comments on the question for some interesting insights, particularly the use of std::aligned_union which can be used as a generic replacement for the PreallocatedStorage union above.

Related

How to deal with different classes which have the same method?

For example, I have 2 classes (in reality, it's more, that's why I'm asking this question) with the same methods:
class class1{
public:
void init(){
//something
}
void dostuff(){
//something
}
//
};
class class2{
public:
void init(){
//something
}
void dostuff(){
//something
}
//
};
And now a third one in which I want to deal with the two classes in the same manner:
class upclass{
public:
upclass(class12* argclass){
myclass=argclass;
myclass->init();
}
void domorestuff(){
myclass->dostuff();
}
private:
class12* myclass; //pointer to class 1 OR class 2
};
My question is now, do I need multiple constructors and multiple declarations to make it work or is there a way around it? Is it even possible to make "class12" a spacekeeper for these types without preprocessor-directives?
I am sorry to say, this is a wide field and there are really many many possible solution.
But I guess that we are talking about object- oriented programming, derivation and plymorphic functions. What you describe, will be typically solved with a class hierachy.
You have one base class with virtual (polymorphic) functions.
Then you derive other classes from this base class and override the virtual functions from the base class.
In a 3rd step, you create some instances of the derived classes dynamically, during runtime and you store the newly created classes (their address) in a pointer to the base class.
Later, you can call any of the virtual overriden function through the base class pointer. And mechanism behind the scenes will call the correct function for you.
Additionally. You defined some function init. Such a function name suggests the usage of a class-constructor. This will be called automatically in the correct sequence. First the base class constructor and then the derived class constructor.
Please see the below example:
#include <iostream>
#include <string>
class Base {
std::string baseName{};
public:
Base() { // Do initialization stuff
baseName = "Base";
std::cout << "\nConstructor Base\n";
}
virtual void doStuff() { // virtual function
std::cout << baseName << '\n';
}
};
class Derived1 : public Base {
std::string derivedName{};
public:
Derived1() : Base() { // Do initialization stuff
derivedName = "Derived1";
std::cout << "Constructor Derived1\n";
}
void doStuff() override { // Override virtaul function
std::cout << derivedName << '\n';
}
};
class Derived2 : public Base {
std::string derivedName{};
public:
Derived2() : Base() { // Do initialization stuff
derivedName = "Derived2";
std::cout << "Constructor Derived2\n\n";
}
void doStuff() override { // Override virtaul function
std::cout << derivedName << '\n';
}
};
int main() {
Base* base = new Base();
Base* derived1 = new Derived1(); // Store in base class pointer
Base* derived2 = new Derived2(); // Store in base class pointer
base->doStuff();
derived1->doStuff(); // Magic of polymorphism
derived2->doStuff(); // Magic of polymorphism
}
The Base class pointer will accept all classes derived from Base.
Please note. In reality you ould not use raw pointers and also to the constructor differently. This is just fotr demo.
But, you need to read several books about it to get the complete understanding.
You can explicitly write "store one of these" via std::variant and obtain the actual type (when needed) through std::visit:
#include <variant>
using class12 = std::variant<class1*, class2*>;
class upclass {
public:
upclass(class12 argclass): myclass{argclass} {
visit([](auto classn) { classn->init(); }, myclass);
}
void domorestuff() {
visit([](auto classn) { classn->dostuff(); }, myclass);
}
private:
class12 myclass;
};
If those visits get too repetitive, you might consider writing a pretty API to hide them:
class prettyclass12: public std::variant<class1*, class2*> {
private: // both g++ and clang want variant_size<>, a quick hack:
auto& upcast() { return static_cast<std::variant<class1*, class2*>&>(*this); }
public:
using std::variant<class1*, class2*>::variant;
void init() { visit([](auto classn) { classn->init(); }, upcast()); }
void dostuff() { visit([](auto classn) { classn->dostuff(); }, upcast()); }
};
class prettyupclass {
public:
prettyupclass(prettyclass12 argclass): myclass{argclass} { myclass.init(); }
void domorestuff() { myclass.dostuff(); }
private:
prettyclass12 myclass;
};

How to get access to the derived std::shared_ptr?

Suppose I have code like that one, and I want to get access to the myClassB members. How can I do that? I need to use the functionality of functionA.
I can't change it because it is from the 3rd party library. And I need to use functionA to create it, and get values created by it. In this case "Test_1" string
class myClassA {
public:
myClassA(){}
~myClassA(){}
};
class myClassB : public myClassA
{
public:
myClassB(){}
void setString1(std::string newString)
std::string getS1()
private:
std::string privateMember;
};
std::shared_ptr<myClassA> functionA()
{
std::shared_ptr<myClassB> temporary(new myClassB());
temporary->setString1("TEST_1");
return std::move(temporary);
}
int main()
{
std::shared_ptr<myClassA> myPtr; // = functionA(); ??
}
Theoretically, you could use a dynamic_cast (or in this case specifically, std::dynamic_pointer_cast to get the derived pointer type. Like so:
std::shared_ptr<MyClassA> a_ptr = functionA();
std::shared_ptr<MyClassB> b_ptr = std::dynamic_pointer_cast<MyClassB>(a_ptr);
if(b_ptr) {//Check to verify the cast was successful
b_ptr->setString("Test1");
}
There is, however, a major caveat to this. In order for dynamic_cast (and therefore std::dynamic_pointer_cast) to work, your object hierarchy must have a virtual table defined. That means at least one of the methods defined by MyClassA must be declared virtual. The simplest solution is to declare the destructor virtual, since that's good practice whenever you're defining polymorphic objects (since you need it to ensure that any derived classes clean up their resources correctly).
class MyClassA {
public:
MyClassA() = default;
virtual ~MyClassA() = default;
};
Agree with dynamic_cast but without a virtual function table in ClassA, something like this would have to do:
Test This Code
#include <string>
#include <memory>
#include <iostream>
#include <set>
class myClassA {
public:
myClassA(){}
~myClassA(){}
};
class myClassB;
class ClassB_Registry{
private:
ClassB_Registry(){
}
~ClassB_Registry(){
}
public:
static ClassB_Registry* Get(){ static ClassB_Registry obj; return &obj; }
static void Register(myClassB* ptr){
Get()->mPointers.insert(ptr);
}
static void UnRegister(myClassB* ptr){
Get()->mPointers.erase(ptr);
}
static myClassB* Cast(myClassA* ptr){
if(Get()->mPointers.count((myClassB*)ptr) > 0) return (myClassB*)ptr;
return nullptr;
}
private:
std::set<myClassB*> mPointers;
};
class myClassB : public myClassA
{
public:
myClassB(){ ClassB_Registry::Register(this); }
~myClassB(){ ClassB_Registry::UnRegister(this); }
void setString1(std::string newString){privateMember = newString;}
std::string getS1() { return privateMember; }
private:
std::string privateMember;
};
std::shared_ptr<myClassA> functionA()
{
std::shared_ptr<myClassB> temporary(new myClassB());
temporary->setString1("TEST_1");
return std::move(temporary);
}
int main()
{
std::shared_ptr<myClassA> myPtr = functionA(); //??
std::shared_ptr<myClassA> myPtr_a(new myClassA()); //??
myClassB* pDerrived = ClassB_Registry::Cast(myPtr.get()); // bridge the RTTI gap
if(pDerrived)
std::cout << pDerrived->getS1();
pDerrived = ClassB_Registry::Cast(myPtr_a.get()); // works on A pointers to return null
if(pDerrived)
std::cout << pDerrived->getS1() << " \n";
else
std::cout << "Not A Pointer of Type B" << " \n";
}
It's not pretty, but if myClassB had a virtual table as mentioned previously, and all future derived classes used myClassB as the base, then you could bridge the gap for RTTI.

is it ok to clear vector in a destructor

class M {
};
class E {
public:
~E();
private:
MyVector mv;
};
E::~E() {
mv.clear()
}
typedef MyHashMap<M*, E*> EMap;
typedef MyHashMap<M*, E*>::iterator EMapItr;
class A : public class Base {
public:
~A();
const EMap& getEMap() { return p_emap};
virtual void func();
protected:
EMap p_Map;
};
A::~A() {
EMapItr eMItr = p_Map.beginRandom();
for(; eMItr; ++eMItr) {
delete eMItr.value();
}
}
class DB {
public fill(EMap* p_Map);
};
class Derived: public A {
private:
DB dp;
};
class GUI {
public:
void guiFunc();
}
void GUI:guiFunc() {
Derived* d = new Derived;
d->func();
}
void Derived::func() {
db.fill(&p_map);
}
Please note MyHashMap is my customised hashmap . the functionality is same as std:hashmap
Please note MyVector is customise form of std::vector . the functionality is same as std:vector
I do not want to delete Pointer of M class M*
is the following code correct or do yo see any problem in the same
A::~A() {
EMapItr eMItr = p_Map.beginRandom();
for(; eMItr; ++eMItr) {
delete eMItr.value();
}
}
Also do we need to clear the vector as below or it will be automatically taken care
E::~E() {
mv.clear()
}
standard library containers don't need to be cleared in destructors because they take care of their own memory management. It is best to do the same with you custom containers because that is generally expected and anyway the best way to avoid memory issues.

Avoid new when storing base-typed member variable that could be initialized with different derived types

My code structure is like below where multiple classes implement Interface. In Example class I store a pointer to the Interface and new() it in the constructor appropriately (depending on constructor parameters not shown here). I'm looking for ways to avoid using new() in this scenario but haven't got a solution yet. What's the best practice for something like this?
class Interface
{
virtual void Foo() = 0;
};
class A : public Interface
{
void Foo() { ... }
};
class B : public Interface
{
void Foo() { ... }
};
class Example
{
private:
Interface* m_bar;
public:
Example()
{
m_bar = new A(); // deleted in destructor
}
};
There are two ways this is typically done, each with their own merits.
If A is truely defined at compile time, than a typical way to handle this is to simply use a template type:
template <typename T>
class TemplateExample
{
T m_bar;
public:
TemplateExample() : m_bar() {};
}
This has some downsides. TemplateExample<A> becomes unrelated to TemplateExample<B>, the error messages when T doesn't follow the correct interface are pretty obtuse, ect. The upside is this may use duck typing rather than interface typing, and m_bar is a concrete instance.
The other (arguable more common) way is to do the following
class UniquePtrExample
{
std::unique_ptr<Interface> m_bar;
public:
UniquePtrExample() : m_bar(new A()){}
};
This has the benefit of being able to be run time configuratble if you follow a cloable pattern:
class Interface
{
public:
virtual void Foo() = 0;
virtual Interface* clone() const = 0;
};
template <typename T>
class CloneHelper : public Interface
{
public:
virtual Interface* clone() const { return new T(static_cast<const T&>(*this));}
};
class A : public CloneHelper<A>
{
virtual void Foo() { std::cout << 'A' << std::endl; }
};
class B : public CloneHelper<B>
{
virtual void Foo() { std::cout << 'B' << std::endl; }
};
class UniquePtrExample
{
std::unique_ptr<Interface> m_bar;
public:
UniquePtrExample() : m_bar(new A()){}
UniquePtrExample(const Interface& i) : m_bar(i.clone());
};
Note you can further extend the above to have a move variant of the clone function.

Determining size of a polymorphic C++ class

Using the sizeof operator, I can determine the size of any type – but how can I dynamically determine the size of a polymorphic class at runtime?
For example, I have a pointer to an Animal, and I want to get the size of the actual object it points to, which will be different if it is a Cat or a Dog. Is there a simple way to do this, short of creating a virtual method Animal::size and overloading it to return the sizeof of each specific type?
If you know the set of possible types, you can use RTTI to find out the dynamic type by doing dynamic_cast. If you don't, the only way is through a virtual function.
Or you can use typeid, which might be faster than dynamic_cast (also with dynamic_cast you can cast to intermediary types in the hierarchy).
It looks rather bad:
#include <iostream>
#include <typeinfo>
class Creature
{
char x[4];
public:
virtual ~Creature() {}
};
class Animal: public Creature { char x[8];};
class Bird: public Creature { char x[16]; };
class Dog: public Animal { char x[32]; };
class Cat: public Animal { char x[64]; };
class Parrot: public Bird { char x[128]; };
unsigned creature_size(const Creature& cr)
{
if (typeid(cr) == typeid(Animal)) {
return sizeof (Animal);
}
else if (typeid(cr) == typeid(Dog)) {
return sizeof(Dog);
}
else if (typeid(cr) == typeid(Cat)) {
return sizeof(Cat);
}
else if (typeid(cr) == typeid(Bird)) {
return sizeof(Bird);
}
else if (typeid(cr) == typeid(Parrot)) {
return sizeof(Parrot);
}
else if (typeid(cr) == typeid(Creature)){
return sizeof(Creature);
}
assert(false && "creature_size not implemented for this type");
return 0;
}
int main()
{
std::cout << creature_size(Creature()) << '\n'
<< creature_size(Animal()) << '\n'
<< creature_size(Bird()) << '\n'
<< creature_size(Dog()) << '\n'
<< creature_size(Cat()) << '\n'
<< creature_size(Parrot()) << '\n' ;
}
For each new type you'll need to add code to the creature_size function. With a virtual size function you'll need to implement this function in each class as well. However, this function will be significantly simpler (perfectly copy-n-pasteable, which shows there might be both a limitation in the language and a problem with your code design):
virtual unsigned size() const { return sizeof(*this); }
And you can make it abstract in the base class which means that it will be a compiler error if you forget to override this method.
Edit: this is naturally assuming that given any Creature you want to know its size. If you have a strong reason to believe that you are dealing with a Dog - or a subclass of Dog (and you don't care if it is a subclass), then naturally you can use dynamic_cast for an ad hoc test.
If you are able to change source classes' design, you can totally replace dynamic polymorphism (which uses virtual functions) with static polymorphism and use the CRTP idiom:
template <class TDerived>
class Base
{
public:
int getSize()
{ return sizeof(TDerived); }
void print()
{
std::cout
<< static_cast<TDerived*>(this)->getSize()
<< std::endl;
}
int some_data;
};
class Derived : public Base<Derived>
{
public:
int some_other_data1;
int some_other_data2;
};
class AnotherDerived : public Base<AnotherDerived>
{
public:
int getSize()
{ return some_unusual_calculations(); }
// Note that the static_cast above is required for this override to work,
// because we are not using virtual functions
};
int main()
{
Derived d;
d.print();
AnotherDerived ad;
ad.print();
return 0;
}
You can do this when the needed polymorphic behavior of program can be determined at compile-time (like the sizeof case), since the CRTP has not the flexibility of dynamic polymorphism to resolve the desired object at run-time.
The static polymorphism also has the advantage of higher performance by removing virtual-function-call overhead.
If you don't want to templatize Base class or you need to hold different derived instances of Base class in a same location (like an array or a vector), you can use CRTP on a middle class and move the polymorphic behavior to that class (similar to the Polymorphic copy construction example in the Wikipedia):
class Base
{
public:
virtual int getSize() = 0;
void print()
{
std::cout << getSize() << std:endl;
}
int some_data;
};
template <class TDerived>
class BaseCRTP: public Base
{
public:
virtual int getSize()
{ return sizeof(TDerived); }
};
class Derived : public BaseCRTP<Derived>
{
// As before ...
};
class AnotherDerived : public BaseCRTP<AnotherDerived>
{
// As before ...
// Note that although no static_cast is used in print(),
// the getSize() override still works due to virtual function.
};
Base* obj_list1[100];
obj_list1[0] = new Derived();
obj_list1[2] = new AnotherDerived();
std::vector<Base*> obj_list2;
obj_list2.push_back(new Derived());
obj_list2.push_back(new AnotherDerived());
--
Update: I now found a similar but more detailed answer on stackoverflow which explains that if we further derive from the derived classes above (e.g. class FurtherDerived : public Derived {...}), the sizeof will not report correctly. He gives a more complex variant of the code to overcome this.
I can't believe that somebody's invented type_id() instead of implementing proper traits ....
One slightly convoluted way that will also work is to implement this through a Curiously Recurring Template Pattern
#include <iostream>
class Base {
public:
virtual ~Base() {}
virtual size_t getSize() = 0;
};
template <class T>
class BaseT : public Base {
public:
size_t getSize() override { return sizeof(T); }
};
class Child : public BaseT<Child> {};
int main()
{
std::unique_ptr<Base> child(new Child);
std::cout << child->getSize();
}