Let's say I have a class like so:
class A
{
public:
template <class T> static inline T* Create()
{
static_assert(std::is_base_of<A, T>::value);
return new T;
}
protected:
A();
virtual ~A();
}
The goal is all objects of classes that derive from "A" to be created only on the heap. This code will work for objects of type A, since the destructor is not public, but nothing stops the creation of an derived class that creates a public destructor.
Is there any way to achieve this?
Related
Consider the curiously recurring template pattern, can you prevent the following unsafe code to compile?
template <class Derived>
class Base {
public:
void foo()
{
// do something assuming "this" is of type Derived:
static_cast<Derived*>(this)->bar();
}
};
// This is OK
class A: public Base<A>
{
public:
void bar()
{
// ...
}
};
// Crash and burn, should be prevented by the compiler
class B: public Base<A>
{
//...
};
void f()
{
// undefined behavior: B object was static_cast to A
B{}.foo();
}
Is there a way to add some kind of restriction to class Base to prevent the definition of class B to be valid?
You can make Base<D> constructor (or destructor) private and friend D.
You'll need to add
A()=default;
B()=default;
publicly, but when you do, B can't be created. Which is good.
In the normal singleton pattern, the singleton class is effectively "sealed" (cannot be derived):
class A
{
private:
static A m_instance; // instance of this class, not a subclass
// private ctor/dtor, so class can't be derived
A();
~A();
public:
static A& GetInstance() { return m_instance; }
...
};
How would you write a class that is meant to be derived, but whose derived class should only be instantiated once?
How would you write a class that is meant to be derived, but whose derived class should only be instantiated once?
You can use the CRTP to realize that:
template<typename Derived>
class A
{
protected: // Allow to call the constructor and destructor from a derived class
A();
~A();
public:
static T& GetInstance() {
static T theInstance; // Better way than using a static member variable
return theInstance;
}
...
};
And use that like
class B : public A<B> {
// Specific stuff for derived class
};
Note that this way makes most sense, if the base class provides some common implementation (besides the GetInstance() function) realized, based on an interface provided by the derived class.
Whenever a call to the derived class in the base class is needed you can safely use a static_cast<Derived*>(this) to access it (no virtual or pure virtual functions needed):
template<typename Derived>
void A<Derived>::doSomething {
// Execute the functions from Derived that actually implement the
// warranted behavior.
static_cast<Derived*>(this)->foo();
static_cast<Derived*>(this)->bar();
}
Say I have a class:
class Foo{
public:
Foo(){
}
//Is it possible to create a function like this:
virtual Foo* createOb(){
//Should create a new Foo,Bar or Fiz, depending on the actual object type.
}
}
class Bar: public Foo{
public:
Bar(){
}
}
class Fiz: public Foo{
public:
Fiz(){
}
}
Is it possible to have a method createOb() in the base class, so when createOb() is called on an instance of one of the derived classes, that an instance of the derived class is created ?
Yes, it can be done, using CRTP.
Bu first, returning a raw pointer obtained from new is very dangerous. In c++ raw pointers should be used only when they do not have ownership of the pointed object. So I took the liberty to use unique_ptr:
struct Base {
virtual auto create_obj() -> std::unique_ptr<Base>
{
return std::unique_ptr<Base>{};
}
};
// abstract works too:
struct Base {
virtual auto create_obj() -> std::unique_ptr<Base> = 0;
};
template <class Derived>
struct Base_crtp : Base {
auto create_obj() -> std::unique_ptr<Base> override /* final */
{
return std::unique_ptr<Base>{new Derived{}};
}
};
struct D1 : Base_crtp<D1>
{
};
struct D2 : Base_crtp<D2>
{
};
And then:
auto b1 = std::unique_ptr<Base>{new D1{}};
auto b2 = std::unique_ptr<Base>{new D2{}};
auto new_d1 = b1->create_obj();
auto new_d2 = b2->create_obj();
Definitely YES!!!
When a method is declared virtual in base class, and called through the derived class object, then the derived class function gets called (Read vprt, vtable concept in c++).
#include <iostream>
using namespace std;
class A{
public:
virtual A* getobj(){
return new A();
}
};
class B: public A{
public:
B(){cout<<"B constructor"<<endl;}
virtual A* getobj(){
return new B();
}
};
int main()
{
A *a = new B();
A *second = a->getobj();
return 0;
}
In the above code, we are calling the getobj() function using class B's object.
Here the constructor of class B is called twice.
first, for new B() in main
secondly for getobj function call which again creates object of B
This is not an optimal solution, but it works.
In your .h
class Foo{
public:
Foo();
virtual Foo* createOb();
};
class Bar: public Foo{
public:
Bar();
};
class Fiz: public Foo{
public:
Fiz();
};
In your .cpp
#include "Header.h"
Foo::Foo() {}
Foo* Foo::createOb(){
if (dynamic_cast<Bar*>(this)) {
return new Bar();
}
else if (dynamic_cast<Foo*>(this)) {
return new Foo();
}
return nullptr;
}
Bar::Bar() {}
Fiz::Fiz() {}
As already suggested please consider a pure virtual method
No, this is not possible with "pure" inheritance. The classes must override createOb() member function in order to support cloning.
You can see why this is not possible by considering separate compilation of classes. An implementation of one-fits-all createOb() member function must be completed in isolation from Bar and Fiz, making it impossible for the base to know the type of its subclasses.
An implementation with a pure virtual function in the base is very common, though.
Another approach is to use Curiously Recurring Template Pattern (CRTP) to implement cloning. This article explains how it can be done.
I have the following classes in my project
class Base
{
public:
virtual ~Base(){};
}
class Der1: public Base
{
public:
virtual ~Der1(){};
}
class Der2: public Base
{
public:
virtual ~Der2(){};
}
I am holding the objects of these classes as std::shared_ptr. I need to provide a custom deleter for all the objects that are either of type Base or any of its derived types.
The code I want in the deleter method will be doing the same thing for all these object, say
class Deleter
{
public:
void operator()( Base * b )
{
//Do something
delete b;
}
}
Instead of providing the deleter during the construction of each objects like
std::shared_ptr< Der1 > pDer1( new Der1(), Deleter() );
std::shared_ptr< Der2 > pDer2( new Der2(), Deleter() );
Is there a way to specify something like "for all the shared pointers to objects of type Base or its derived types use Deleter for deletion?
As deleter class is just taken in the constructor of shared_ptr how can someone specify a deleter for a particular type?
I'd write a creation/factory function in Base, returning the shared_ptr for the correct derived type. Something to this effect:
class Base
{
//...public...
template <class Derived>
static std::shared_ptr<Base> create()
{
return std::shared_ptr<Base>(new Derived, Deleter());
}
};
EDIT: Function needs to be static...
If derived has more than one parameter, that can be solved with variadic templates and perfect forwarding.
EDIT:
Like this (For more than one parameter derived constructor):
#include <iostream>
#include <memory>
struct Base;
struct Deleter
{
void operator()(Base* b);
};
struct Base
{
//...public...
template <class Derived, class ... Args>
static std::shared_ptr<Base> create(Args&&... args)
{
return std::shared_ptr<Base>(new Derived(std::forward<Args>(args)...), Deleter());
}
virtual ~Base(){}
};
void Deleter::operator()(Base* b){ delete b; }
struct Derived : Base
{
Derived(int a, int b, int c)
{
}
};
int main() {
std::shared_ptr<Base> p = Base::create<Derived>(1,2,3);
return 0;
}
How can I return the object or call the getInstance of derived class whose base is singleton
You would have to use virtual static method, which is not supported in C++ (It's supported in Delphi, as far as I remember - a curiosity).
You have to decide, whether there's only one instance of both classes or of each class (eg. if you create a Derived instance by GetInstance, should you be able to create Base instance).
There is no way to solve this problem inside these classes, you have to create a class factory. Something like that (I've ommited the singleton implementation to make the idea more clear - obviously you know, how to implement one)
class SingletonFactory
{
template<typename T>
static T * GetInstance()
{
return T.GetInstance();
}
};
class Base
{
friend class SingletonFactory;
private:
static Base * GetInstance()
{
// ...
}
protected:
Base()
{
}
};
class Derived : public Base
{
friend class SingletonFactory;
private:
static Derived * GetInstance()
{
}
protected:
Derived()
: Base()
{
}
};
// (...)
Derived * d = SingletonFactory::GetInstance<Derived>();