I have seen solutions (including in this site) to the problem of having to implement a clone method in a class, so it returns a heap-allocated clone of itself even if we only have the Baseclass.
The problem come up when you have to implement in a lot of classes the same method again and again, and I remember a way of doing this when you only have to inherit from a template class (name it Cloneable) so it implements it, but the way i'm trying to do it doesn't work:
template<typename T, typename B> class Cloneable{
public:
B* clone(){return new T(*this);}
};
class Bottom {
public:
virtual void sayhi() = 0;
virtual Bottom* clone() = 0;
};
class Middle: public Cloneable<Middle, Bottom>, public Bottom {
public:
void sayhi() override {cout << "Hi from the Middle" << endl;}
};
//class Top: public Middle ...?
int main() {
Bottom* b1 = new Middle();
b1->sayhi();
delete b1;
}
I remember that the person that showed this to me actually did it with just one argument in Cloneable, but anyways, i would thank any way that you can imagine of doing this.
You could use the Curious Recurring Template Pattern where a derived class actually derives from an instanciation of it base class depending on itself. Demo:
#include <iostream>
template<typename T>
class Clonable {
public:
T* clone() {
return new T { * static_cast<T *>(this)};
}
};
template<class T>
class Base : public Clonable<T> {
public:
int x = 2;
virtual ~Base() {}
};
class Derived : public Base<Derived> {
public:
int y = 3;
};
int main() {
Base<Derived> *d = new Derived;
static_cast<Derived *>(d)->y = 6;
Derived *c = d.clone(); // we are even cloning from a Base *!
std::cout << c->x << ' ' << c->y << '\n';
delete c;
delete d;
}
It compiles with no warning and correctly outputs 2 6, proving that no slicing occurred.
Your Cloneable is missing a cast. this is a Cloneable *, it needs to be cast to T * to be passed to the copy constructor.
template<typename T, typename B> class Cloneable : public B
{
public:
B* clone() override { return new T(*static_cast<T*>(this)); }
};
class Base
{
public:
virtual Base* clone() = 0;
};
class Derived : public Cloneable<Derived, Base>
{
};
See it live
This doesn't stop someone from further subclassing Derived, and forgetting to reimplement clone for that grandchild class.
class Oops : public Derived {};
int main() {
Oops o;
Base * pb = o.clone();
assert(typeid(*pb) != typeid(o));
}
Related
I need to copy an object of a polymorphic class having a base pointer. I know that I can implement a virtual method for this. But what if the base class should not be abstract? Leaving the method without pure-specifier can lead to run-time bugs, if you forget reimplement it in the derived. It's uncomfortable. What is the best way to handle this?
There are good reasons why you should never want to instantiate a base class.
If you do need to make a empty final class use the following.
class IBase
{
virtual void SharedCode()
{
1 + 1;
/// code here
};
virtual void AbstractDecalration() = 0;
};
class Base final: IBase
{
void AbstractDecalration() override;
};
Base b{};
All Future Derived classes will be able to use the SharedCode of IBase and you will have a Instantiated class of Base that is final. This is for future proofing your code base.
However I realize that is not the question you asked so here is a implementation were I use a simple check to the vtable pointer of the class to see if I have the correct class.
This is a runtime check and doesn't work across libraries use dynamic_assert if that is the case.
#include <memory>
#include <type_traits>
#include <assert.h>
class Base {
public:
auto clone() const
{
return std::unique_ptr<Base>(this->clone_impl());
}
private:
virtual Base* clone_impl() const
{
Base b{};
int* bVtablePtr = (int*)((int*)&b)[0];
int* thisVtablePtr = (int*)((int*)this)[0];
assert(bVtablePtr == thisVtablePtr);
return new Base(*this);
}
};
class Derived : public Base
{
auto clone() const
{
return std::unique_ptr<Derived>(this->clone_impl());
}
virtual Derived* clone_impl() const
{
return new Derived();
}
};
class Falty : public Base{};
int main(){
std::unique_ptr<Derived> good(new Derived());
std::unique_ptr<Falty> falty(new Falty());
good->clone(); // oke
falty->clone(); // this function asserts at runtime
}
Note the private clone_impl and public unique_ptr retuning clone method.
Very usefull to prevent memory leaks in your code
You can achieve what you want by introducing another abstract base class plus using CRPT for clone function. Then, clone will be automatically implemented in all derived classes "for free" (without manual retyping). Example:
struct Abstract
{
virtual ~Abstract() {}
virtual Abstract* clone() const = 0;
virtual void say() const = 0;
};
template <typename B, typename D>
struct AbstractCloneable : B
{
virtual B* clone() const override
{
return new D(static_cast<const D&>(*this));
}
};
// original base class
struct Base : AbstractCloneable<Abstract, Base>
{
virtual void say() const override
{
std::cout << "Base" << std::endl;
}
};
// original derived class #1
struct Derived1 : AbstractCloneable<Base, Derived1>
{
virtual void say() const override
{
std::cout << "Derived1" << std::endl;
}
};
And a test program:
int main()
{
std::unique_ptr<Abstract> ptr1 = std::make_unique<Base>();
ptr1->say();
std::unique_ptr<Abstract> ptr1_copy{ ptr1->clone() };
ptr1_copy->say();
std::unique_ptr<Abstract> ptr2 = std::make_unique<Derived1>();
ptr2->say();
std::unique_ptr<Abstract> ptr2_copy{ ptr2->clone() };
ptr2_copy->say();
}
Which outputs:
Base
Base
Derived1
Derived1
Live demo: https://godbolt.org/z/3FeSTd
See this article for more details and explanations: C++: Polymorphic cloning and the CRTP (Curiously Recurring Template Pattern).
I have two classes, let's say Base and Derived:
class Base {
public:
virtual ~Base() = 0;
};
class Derived : public Base {};
and a function foo:
auto foo (Derived* d) {
...
}
Is it possible to automatically downcast its argument? So I could do something like this:
Base* b = new Derived();
foo(b);
Basically I would like to write this without explicit casting it before function call.
I read something about conversion operators/constructors but they seem not useful in my case, do you have any other idea?
Edit: Sorry, I oversimplified the question with 2 classes and just a function. But actually I've got a library of 50-ish functions and 3 classes (a superclass and 2 subclasses). This unfortunately makes the easiest and cleanest solutions unsuitable because in my opinion (correct me if I am wrong) they scale bad.
I can think of three possible solutions, depending on your needs. I've replaced raw pointers with unique_ptrs in my examples.
Case 1: You don't need the base type of each derived type to be the same.
Use CRTP to allow the base type to invoke itself as a derived type. Example implementation:
template <typename DerivedType>
class Base {
template <typename F>
auto invoke_as_derived(F&& f) {
return std::forward<F>(f)(static_cast<DerivedType*>(this));
}
};
class Derived : public Base<DerivedType> {};
Usage:
std::unique_ptr<Base<Derived>> b = std::make_unique<Derived>();
b->invoke_as_derived(foo);
Since you mentioned using a list of Base pointers, this probably won't work for you.
Case 2: You need a shared base type but only have one layer in your type hierarchy and no virtual methods.
Use std::variant and std::visit.
class Derived {};
using Base = std::variant<Derived, /* other derived types */>;
auto foo(Derived*) { ... }
class FooCaller {
operator ()(Derived& d) {
return foo(&d);
}
// Overload for each derived type.
}
Usage:
Base b = Derived();
std::visit(FooCaller{}, b);
Case 3: You need a single base type but also want virtual methods and/or additional layers in your type hierarchy.
You might try the visitor pattern. It takes some boilerplate, but it may be the best solution depending on your needs. Sketch of the implementation:
class Visitor; // Forward declare visitor.
class Base
{
public:
virtual void accept(Visitor& v) = 0;
};
class Derived : public Base
{
public:
void accept(Visitor& v) final { v.visit(*this); }
};
struct Visitor
{
virtual void visit(Derived&) = 0;
// One visit method per derived type...
};
struct FooCaller : public Visitor
{
// Store return value of call to foo in a class member.
decltype(foo(new Derived())) return_value;
virtual void visit(Derived& d)
{
return_value = foo(&d);
}
// Override other methods...
};
Usage:
std::unique_ptr<Base> b = std::make_unique<Derived>();
FooCaller foo_caller;
b->accept(foo_caller);
You could write a visitor that takes a function to apply to the element so you don't have to repeat this for all of your many functions. Alternatively, if you can alter the functions themselves, you could replace your functions with visitor types.
Edit: Simplifying the call syntax back down to foo(b)
Define an overload per function overload set to which you want to pass Base objects. Example, using the 3rd technique:
auto foo(Base* b) {
FooCaller foo_caller;
b->accept(foo_caller);
return std::move(foo_caller.return_value);
}
Now foo(b.get()) will delegate to the appropriate overload of foo at run-time.
The usual approach would not be to downcast, but to use virtual functions. I.e. put void foo() inside of the class.
#include<iostream>
class Base {
public:
virtual ~Base() = default;
virtual void foo() { std::cout << "Base foo()\n"; }
};
class Derived : public Base {
public:
void foo() override { std::cout << "Derived foo()\n"; }
};
int main()
{
Base* b = new Derived();
b->foo();
delete b;
}
outputs:
Derived foo()
If you want to make it impossible to call Base::foo(), you can set
class Base {
public:
virtual ~Base() = default;
virtual void foo() = 0;
};
making Base an abstract class.
But if you really want to call foo(b), you can use a (templated) helper function. E.g.:
#include<iostream>
class Base {
public:
virtual ~Base() = default;
virtual void foo() = 0;
};
class Derived : public Base {
public:
void foo() override {
std::cout << "Derived foo()\n";
}
};
template<typename T>
void foo(T* t)
{
t->foo();
}
int main()
{
Base* b = new Derived();
foo(b);
delete b;
}
First of all im trying to create a games engine with similar architecture to Unity. I have an Object class, a GameObject class which inherits from Object. Within GameObject class i am trying to make a template class that will let you add any component onto the game object, although i get a dynamic pointer cast error which i cant seem to solve.
Heres the GameObject class:
class GameObject : public Object
{
public:
template<class T>
std::shared_ptr<T> addChildComponent()
{
std::shared_ptr<T> temp_component(new T());
temp_component->gameObject = std::dynamic_pointer_cast<GameObject>(shared_from_this());
m_components.push_back(temp_component);
return temp_component;
}
template<class T>
std::shared_ptr<T> getComponent()
{
for (int i = 0; i < m_components.size(); i++)
{
std::shared_ptr<T> t;
t = m_components.at(i);
if (t.get() != NULL)
{
return t;
}
}
return std::shared_ptr<T>();
}
Furthermore this is the Object Class which it inherits from:
class Object : public std::enable_shared_from_this<Object>
{
friend class GameObject;
public:
Object();
~Object();
void makeName(std::string _name);
std::string getName();
private:
std::string name;
};
The error means that whatever you are trying to cast from does not have any virtual members. A base class of a virtual inheritance chain should always have a virtual destructor at minimum and then you would no longer get this error.
As an example, the following would exhibit the error you have:
class base1
{
int a;
};
class derived1: public base1
{};
...
derived1 d1;
base1 * pb1 =&d1;
derived1 * pd1 = dynamic_cast<derived1*>(pb1);
While the next would not:
class base2
{
int a;
public:
virtual ~base1() {}
};
class derived2 : public base2
{};
...
derived2 d2;
base2 * pb2 = &d2;
derived2 * pd2 = dynamic_cast<derived2*>(pb2);
Long story short, what I want here is to declare a templated type in a base class and be able to access that type A<T> such that the base class B contains it and the derived class C is able to access it as C::A<T>. I did try declaring an int inside of class B and that can be accessed from the derived C class as C::int, here's the error!
||In constructor ‘D::D()’:|
|74|error: no match for ‘operator=’ (operand types are ‘A<C*>’ and ‘A<B*>’)|
|4|note: candidate: A<C*>& A<C*>::operator=(const A<C*>&)|
|4|note: no known conversion for argument 1 from ‘A<B*>’ to ‘const A<C*>&’|
And this is the code that does compile ( comment A<B*> i; and uncomment A<C*> i; to get the error).
#include <iostream>
//class with a template parameter
template <class a>
class A
{
private:
int somevalue;
public:
A(){}
~A(){}
void print()
{
std::cout<<somevalue<<std::endl;
}
};
//1. could forward declare
class C;
class B
{
protected:
A<B*> i;
//2. and then use
//A<C*> i;
public:
B(){}
~B(){}
A<B*> get()
{
return i;
}
/*
//3. use this return instead
A<C*> get()
{
return i;
}
*/
};
//specialization of B that uses B's methods variables
class C : public B
{
protected:
public:
C(){}
virtual ~C(){}
void method()
{
B::i.print();
}
};
//class D that inherits the specialization of C
class D : public C
{
private:
A<B*> i;//works
//4. but I want the inherited type to work like
//A<C*> i;// so that the type C* is interpreted as B*
public:
D()
{
this->i = C::i;
}
~D(){}
};
///////////////////////////////////////////////////////////////////////
int main()
{
D* d = new D();
delete d;
return 0;
}
But okay what if we tried this std::list<template parameter> LIST and then plug that in? That's the problem A<T> is std::list.
As far as I understand your issue now you seem to have a std::list<Base *> (renamed B to Base for clarity) and want to fill an std::list<Concrete*> (renamed C to Concrete, it's derived from Base) with it.
For that you need to iterate over the Base* pointers, checking for each whether it can be downcast to a Concrete* and if so adding it to the std::list<Concrete*>. You need to think about what to do if the downcast fails, too.
For all of this to work your Base needs to be a polymorphic base class, that is it must contain a virtual member function (don't forget to make the destructor virtual). Also note that this sounds like a catastrophe waiting to happen in terms of managing ownership of those pointers.
template<typename Base, typename Concrete>
std::list<Concrete*> downcast_list (std::list<Base*> const & bases) {
std::list<Concrete*> result;
for (auto const base_ptr : bases) {
Concrete * concrete_ptr = dynamic_cast<Concrete*>(base_ptr);
if (concrete_ptr != nullptr) {
result.push_back(concrete_ptr);
} else {
// Error or ignore?
}
}
return result;
}
Note: a more idiomatic version of this would use iterators.
I found the pattern to my problem, it's actually really simple and it serves as the base for encapsulating a class type a (which is a template parameter to be passed around, try looking at my question as a reference to class a). The pattern is shown below, it's generally what I wanted. I found it on this webpage Using Inheritance Between Templates chapter 7.5 from the book entitled OBJECT-ORIENTED
SOFTWARE DESIGN
and CONSTRUCTION
with C++ by Dennis Kafura. I'll copy it below the edited code for the sake of future reference in case anyone else needs it.
template <class a>
class B
{
private:
public:
B();
~B();
};
template <class a>
class C : public B<a>
{
public:
C();
~C();
};
This is the code it was adapted from.
template <class QueueItem> class Queue
{
private:
QueueItem buffer[100];
int head, tail, count;
public:
Queue();
void Insert(QueueItem item);
QueueItem Remove();
~Queue();
};
template <class QueueItem> class InspectableQueue : public Queue<QueueItem>
{
public:
InspectableQueue();
QueueItem Inspect(); // return without removing the first element
~InspectableQueue();
};
Try changing this:
#include <iostream>
//class with a template parameter
template <class a>
class A {
private:
int somevalue;
public:
A(){}
~A(){}
void print() {
std::cout<<somevalue<<std::endl;
}
};
//1. could forward declare
class C;
class B {
protected:
A<B*> i;
//2. and then use
//A<C*> i;
public:
B(){}
~B(){}
A<B*> get() {
return i;
}
/*/3. use this return instead
A<C*> get() {
return i;
} */
};
//specialization of B that uses B's methods variables
class C : public B {
protected:
public:
C(){}
virtual ~C(){}
void method() {
B::i.print();
}
};
//class D that inherits the specialization of C
class D : public C {
private:
A<B*> i;//works
//4. but I want the inherited type to work like
//A<C*> i;// so that the type C* is interpreted as B*
public:
D() {
this->i = C::i;
}
~D(){}
};
int main() {
D* d = new D();
delete d;
return 0;
}
To Something Like This:
#include <iostream>
//class with a template parameter
template <typename T>
class Foo {
private:
T value_;
public:
Foo(){} // Default
Foo( T value ) : value_(value) {}
~Foo(){}
void print() {
std::cout<< value_ << std::endl;
}
};
class Derived;
class Base {
protected:
Foo<Base*> foo_;
Base(){} // Default;
virtual ~Base(){}
// Overload This Function
template<typename T = Base>
/*virtual*/ Foo<T*> get();
/*virtual*/ Foo<Base*> get() { return this->foo_; }
/*virtual*/ Foo<Derived*> get();
};
class Derived : Base {
public:
Derived() {}
virtual ~Derived() {}
void func() {
Base::foo_.print();
}
void Foo<Derived*> get() override { return this->foo_; }
};
And this is as about as far as I could get trying to answering your question...
There are objects that you are not using in your code
There are methods that aren't being called.
It is kind of hard to understand the direction/indirection
of what you mean to do with the inheritance tree.
You are inheriting from a base class without a virtual destructor
And probably a few other things that I can not think of off the top of my head right now.
I'd be more than willing to try and help you out; but this is as far as I can go with what you currently are showing.
EDIT -- I made changes to the base & derived classes and removed the virtual keyword to the overloaded function template declarations - definitions belonging to those classes.
SOLVED!
I want to create an array of different typed objects using templates.
Therefore I have a non-template class (Base), and a derived template class from Base class.
What I want to know is how can i access to derived class' generic value (T val)?
class Base{
public:
// a function returns T val, it will be implemented in Derived class
// EDIT : virtual function here
};
template<class T>
class Derived: public Base {
public:
T val;
Derived(T x) {
val = x;
}
// implementation.. it returns val
// EDIT : Implementation of virtual function
};
Solution: dynamic_cast, Note that Base class should have at least one virtual function.
Base *p[2];
p[0] = new Derived<int>(24);
p[1] = new Derived<double>(82.56);
int a = dynamic_cast<Derived<int>*>(p[0])->val; // casts p[0] to Derived<int>*
double b = dynamic_cast<Derived<double>*>(p[1])->val; // casts p[1] to Derived<double>*
cout << a << endl;
cout << b << endl;
Last time i checked, You cannot acess derived class members from a base class(non virtual).
You could modify your code this way since you are using templates.The type and value are passed to base class at construction and you can then use it.
template<typename T>
class Base {
T ini;
public:
Base(T arg){ini = arg;}
T ret(){return ini;}
};
template<class T>
class Derived: public Base<T> {
public:
T val;
Derived(T x) : Base<T>(x) {
//Base(x);
val = x;
}
// implementation.. it returns val
};
You can then instantiate it as usual and use it.
Derived<int> e(5);
e.ret();
It look like you want CRTP
The idea is to access the derived class members inside the base class. Note that you won't be able to contain an heterogeneous list of them.
template<typename D>
struct Base {
void doThings() {
// access the derived class getT function
auto var = static_cast<D&>(*this).getT();
cout << var << endl;
}
};
template<typename T>
struct Derived : Base<Derived> {
T getT() {
return myT;
}
private:
T myT;
};