I have an access to an external library that provides a function that returns a pointer to an abstract class Foo, I want to copy that class but the library is pre-compiled so I cannot add any new functions like the virtual clone function https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Virtual_Constructor.
Is there any other way to copy the contents of the pointer?
class Foo // private precompiled class I cannot add methods to
{
virtual void F() = 0;
};
class FooChild : public Foo
{
void F() override
{
}
};
static Foo* getFoo()
{
return new FooChild();
};
int main()
{
Foo* f = getFoo();
Foo* fCopy = new Foo(f); //cannot do that
return 0;
}
Your only option is a long if else if chain, based on typeid(*f), with a branch for every possible type.
Foo *copy = nullptr;
if (typeid(*f) == typeid(FooChild))
copy = new FooChild(static_cast<FooChild &>(*f));
else if // ... same for every child class
If you're not forced to use Foo in your main() there's a way to make this work if you use a FooBase subclass instead.
class Foo
{
public:
virtual ~Foo() = default;
virtual void f() = 0;
};
class FooBase: public Foo
{
public:
virtual FooBase* clone() = 0;
};
template <class Derived>
class FooBase_: public FooBase {
public:
FooBase* clone() override { return new Derived(static_cast<Derived&>(*this)); }
};
class FooChild1: public FooBase_<FooChild1> {
public:
FooChild1() = default;
FooChild1(const FooChild1&) = default;
void f() override { std::cout << "FooChild1\n"; }
};
class FooChild2: public FooBase_<FooChild2> {
public:
FooChild2() = default;
FooChild2(const FooChild2&) = default;
void f() override { std::cout << "FooChild2\n"; }
};
int main()
{
FooBase* f1 = new FooChild1;
FooBase* f1Copy = f1->clone();
f1->f();
f1Copy->f();
FooBase* f2 = new FooChild2;
f2->f();
delete f1;
delete f1Copy;
delete f2;
return 0;
}
FooBase_ is a CRTP generating a specific clone() method for each FooChildN concrete class, avoiding repetition.
Demo here: https://godbolt.org/z/nva75Gx4x
Related
I have a class derived from an interface and a friend class of the derived class. I want to access the members of derived class which is instantiated as interface. It looks like this:
Interface:
class AInterface
{
public:
virtual ~AInterface() = default;
virtual void set(int a) = 0;
};
Derived class A with friend class B:
class B;
class A : public AInterface
{
public:
~A() override {}
void set(int a) override
{
mem = a;
}
private:
friend class B;
int mem = 0;
};
class B:
class B
{
public:
B()
{
a = new A();
a->set(3);
}
int get_a()
{
// Access mem since it's a friend class
return a->mem;
}
private:
AInterface *a;
}
main:
int main()
{
B *b = new B();
std::cout << b->get_a() << std::endl;
return 0;
}
The program does not compile saying AInterface has no member named 'mem'.
Do I need getter functions in the interface and implement it in A to achieve this or is there any other way to do it?
Now work
#include <iostream>
using namespace std;
class AInterface
{
public:
virtual ~AInterface() = default;
int getMem() { return mem; }
virtual void set(int a) = 0;
protected:
int mem = 0;
};
class A : public AInterface
{
public:
~A() override {}
void set(int a) override
{
mem = a;
}
};
class B
{
public:
B()
{
a = new A{};
a->set(3);
}
int get_a()
{
// Access mem since it's a friend class
return a->getMem();
}
private:
AInterface *a;
};
int main()
{
B *b = new B();
std::cout << b->get_a() << std::endl;
return 0;
}
Method which is override by child and is pure, should be virtual.
If each class (child) Interface, variable int mem should be protected in interface.
Now works fine, like you want.
Add getter getMem()
Version with friend
#include <iostream>
using namespace std;
class AInterface
{
public:
virtual ~AInterface() = default;
virtual void set(int a) = 0;
protected:
friend class B;
int mem = 0;
};
class A : public AInterface
{
public:
~A() override {}
void set(int a) override
{
mem = a;
}
};
class B
{
public:
B()
{
a = new A{};
a->set(3);
}
int get_a()
{
// Access mem since it's a friend class
return a->mem;
}
private:
AInterface *a;
};
int main()
{
B *b = new B();
std::cout << b->get_a() << std::endl;
return 0;
}
In your class B.
class B
{
//...
int get_a()
{
return a->mem; // but a is a AInterface* !!!
}
private:
AInterface *a; // That's not an A*, but an AInterface*
};
You have 2 options.
use dynamic_cast<>
int B::get_a()
{
A* p = dynamic_cast<A*>(a);
if (p)
return p->mem;
// a is not an A*, it's another AInterface*-type object !!!
// What should you do?
throw something_or_other(); // throw?
return -1; // return an error code?
}
// or maybe add.. so you can check for errors before calling get_a()
A* B::get_A_ptr() const
{
return dynamic_cast<A*>(a);
}
dynamic_cast works fine, but can slow down your app if you need to make frequent reads of a->mem.
Store a in an A*, which is probably what you meant to do from the start...
class B
{
// ...
private:
A* a; // now a->A::mem is visible.
};
Since you explicitly call new A in B's constructor, I think option 2 is better for your case.
I have a situation that I am attempting to write some c++ code to implement and I think I need to use templates but I am unsure. I don't think I understand templates well enough and just want to know if I am on the right track. I have never implemented a class that requires templates before.
I have a base class that needs to instantiate a new class and store it on a list for future access. The class that needs to be instantiated is derived from a base class that has one virtual method. After the class is instantiated, this method is called and the new instance is stored on a list. Another method is provided to get the instantiated object.
Say the virtual class is named foo:
class foo
{
public:
virtual void process() = 0;
}
the user would create a class bar:
class bar : public foo
{
public:
void process() {};
}
The class that I think needs to be a template class:
class Filter<Foo* T>
{
public:
// use value junk to derive foo
// and put the new instance on a std::list
add(Junk* junk);
T get();
private:
std::list<T> mFooList;
}
void Filter::add(Junk* junk)
{
T* foo = new T();
foo.p(junk);
mFooList.push_back(foo);
}
T* Filter::get()
{
if(!mFoolist.empty())
{
T* res = mFooList.back();
mFooList.pop_back();
return res;
}
return nullptr;
}
You don't need to use a templatevin this situation. In c++ a derived class can be assigned to a pointer of the base class. You can just use foo pointers.
class foo
{
public:
virtual void process();
};
class bar1: public foo
{
public:
void process();
};
class bar2 : public foo
{
public:
void process();
};
class filter
{
private:
std::list<foo*> _foos;
public:
foo* get();
void add(foo* f);
};
void filter::add(foo* f)
{
_foos.push_back(f);
}
foo* filter::get()
{
if(!_foos.empty())
{
return _foos.pop_back();
}
return nullptr;
}
You can then just add and get foos and bars
filter fil;
fil.add(new foo());
fill.add(new bar1());
fill.add(new bar2());
foo f = fill.get();
while(f != nullptr)
{
f->process();
delete f;
f = fil.get();
}
I am very new to c++ so I am trying to get a feeling of how to do things the right way in c++. I am having a class that uses one of two members. which one gets determined at instantiation. It looks something like
main() {
shared_pointer<A> a = make_shared<A>();
if ( checkSomething ) {
a->setB(make_shared<B>());
} else {
a->setC(make_shared<C>());
}
a->doStuff();
class A {
public:
doStuff() {
/*here I want to do something like call
m_b->doStuff() if this pointer is set and m_c->doStuff() if
that pointer is set.*/
}
setB( B* p ) { m_b = p; }
setC( C* p ) { m_c = p; }
B* m_b;
C* m_c;
}
}
B and C are some classes with doStuff() member function
There are many members like doStuff. Ideally I would avoid checking for nullptr in each of them. What is the best/most efficient/fastest way to create a switch between those two members?
Is there a way to use a static pointer so that I have a member
static **int m_switch;
and do something like
m_switch = condition ? &m_b : &m_c;
and call
*m_switch->doStuff();
Does the compiler here also replace the extra pointer hop because it is a static?
Is there any other smart way to do those switches?
Normally, class A would be an interface class, which both B and C would inherit and implement. But it sounds like you cannot do this for whatever reason.
Since you want to emulate this, you can start by making the interface:
class A_interface
{
public:
virtual void doStuff() = 0;
virtual void doThings() = 0;
virtual void doBeDoBeDo() = 0;
};
And then you make a template wrapper:
template< class T >
class A : public A_interface
{
public:
void doStuff() override { target.doStuff(); }
void doThings() override { target.doThings(); }
void doBeDoBeDo() override { target.doBeDoBeDo(); }
private:
T target;
};
This essentially does half of what your own example class A was trying to do, but now you can use a common interface. All you need to do is construct the correct templated version you want:
std::shared_ptr<A_interface> a;
if( checkSomething ) {
a = std::make_shared<A<B>>();
} else {
a = std::make_shared<A<C>>();
}
a->doStuff();
You need to have both members implement a common interface to use them similarly. But in order to do that, you need to define the interface and relay the calls to the B and C classes.
// existing classes
class B
{
public:
void doStuff() { std::cout << "B"; }
};
class C
{
public:
void doStuff() { std::cout << "C"; }
};
// define your interface
class I
{
public:
virtual void doStuff() = 0;
};
// new classes
class D : public B, public I
{
public:
void doStuff() override { B::doStuff(); }
};
class E : public C, public I
{
public:
void doStuff() override { C::doStuff(); }
};
// your A class
class A
{
public:
D* b = nullptr; // now type D
E* c = nullptr; // now type E
// your toggle
I* getActive()
{
if (b)
return b;
else
return c;
}
// simple doStuff() function
void doStuff()
{
getActive()->doStuff();
}
};
int main()
{
A a;
if (true)
a.b = new D; // need to initialize as D
else
a.c = new E; // need to initialize as E
a.doStuff(); // prints B
}
But typing this up made me realize that defining D and E could get really tiresome and against what you're trying to save. However, you can define a template to create them like #paddy has done.
There's no one-size-fits-all solution for your problem. What to use depends on your particular problem. A few possible answers:
Interfaces
Strategy Pattern
Pointers (to hold a function or class which implements doStuff)
An interface is like a contract. Any class which inherits from the interface must implement its members. For instance,
class IDoesStuff
{
public:
virtual ~IDoesStuff() {};
virtual void DoStuff() = 0;
};
Can now be used by other classes:
class Foo : public IDoesStuff
{
public:
virtual void DoStuff()
{
// ....
}
};
class Bar : public IDoesStuff
{
public:
virtual void DoStuff()
{
// ....
}
};
And now, in general, one may do:
Foo foo;
IDoesStuff *stuffDoer= &foo;
stuffDoer->doStuff();
This can be used in your particular use case as follows:
class A
{
IDoesStuff *stuffDoer; // Initialize this at some point.
public:
void doStuff() { stuffDoer->doStuff(); }
};
First you must change your memebr variables m_b and m_c to std::shared_ptr.
Add a member variable of type std::function(void()) to hold the target function you want to call. In your sample it is do_stuf.
In your setter functions you can bind target function to your std::function and in do_stuf just call std::function.
(You need a C++11 compiler)
class B
{
public:
void doStuff()
{
}
};
class C
{
public:
void doStuff()
{
}
};
class A
{
public:
void doStuff()
{
m_target_function();
}
void setB(std::shared_ptr<B> p)
{
m_b = p;
m_target_function = std::bind(&B::doStuff, m_b.get());
}
void setC(std::shared_ptr<C> p)
{
m_c = p;
m_target_function = std::bind(&C::doStuff, m_c.get());
}
std::shared_ptr<B> m_b;
std::shared_ptr<C> m_c;
std::function<void()> m_target_function;
};
int _tmain(int argc, _TCHAR* argv[])
{
std::shared_ptr<A> a = std::make_shared<A>();
bool use_B = false;
if (use_B)
{
a->setB(std::make_shared<B>());
}
else
{
a->setC(std::make_shared<C>());
}
a->doStuff();
}
I have a need to clone a derived class given only a reference or pointer to the base class. The following code does the job, but doesn't seem elegant, because I'm putting boilerplate code into many derived classes C, D, E that are siblings of B (not shown) that just calls the default copy constructor of each. Isn't that what the default copy constructor is for, if only it could be virtual?
Is there a better way?
Making a virtual assignment operator would be wrong, as I don't want C to assign to B, B to D, etc, just clone B, C, D or E.
#include <iostream>
using namespace std;
class A {
public:
virtual ~A() {}
virtual A* clone()=0;
};
class B : public A {
int i;
public:
virtual A* clone() {
cout << "cloned B" << endl;
return new B(*this);
}
virtual ~B() { cout << "destroyed b" << endl; }
};
int main() {
A* a = new B();
A* aa = a->clone();
delete a;
delete aa;
return 0;
}
You could always stick all the cloning logic into its own class in the middle of the hierarchy:
template <class Derived, class Base>
class CloneCRTP : public Base {
public:
Derived* clone() const override {
return new Derived(static_cast<Derived const&>(*this));
}
};
And then:
class B : public CloneCRTP<B, A>
{
int i;
public:
virtual ~B() { cout << "destroyed b" << endl; }
};
No more boilerplate.
You can rely on the CRTP idiom.
It follows a minimal, working example:
struct B {
~virtual ~B() { }
virtual B* clone() = 0;
};
template<class C>
struct D: public B {
B* clone() {
return new C{*static_cast<C*>(this)};
}
};
struct S: public D<S> { };
int main() {
B *b1 = new S;
B *b2 = b1->clone();
delete b1;
delete b2;
}
To achieve clone that works as with covariant return type, there is a need for some more complicated CRTP:
class Shape {
// virtual
virtual Shape* do_clone() const = 0;
public:
virtual ~Shape() {}
// non-virtual
Shape* clone() const {
return do_clone();
}
// ...
};
template <class Derived, class Base>
class CloneCRTP : public Base {
// virtual
Base* do_clone() const override {
return new Derived(static_cast<Derived const&>(*this));
}
public:
// non-virtual
Derived* clone() const {
return static_cast<Derived*>(do_clone());
}
};
Usage:
class Rectangle: public CloneCRTP<Rectangle, Shape> { /*...*/ };
class Triangle: public CloneCRTP<Triangle, Shape> { /*...*/ };
int main() {
Rectangle* r1 = new Rectangle{};
// getting the proper type from clone:
Rectangle* rcopy = r1->clone();
delete rcopy;
delete r1;
Triangle t1{};
// getting the proper type from clone:
Triangle* tcopy = t1.clone();
delete tcopy;
}
Code: http://coliru.stacked-crooked.com/a/339458f8b45299c3
I do it in a generalized way.
Definition:
template <class Class>
class CloneInterface {
public:
Class* copy() const { return new Class{static_cast<Class const&>(*this)}; }
virtual Class* clone() const { return this->copy(); }
};
template <class Derived, class Base>
class CloneCRTP : public Base {
public:
Derived* copy() const { return new Derived{static_cast<Derived const&>(*this)}; }
Base* clone() const override { return this->copy(); }
};
Usage:
class Base : public CloneInterface<Base> {
private:
int a = 0;
public:
virtual ~Base() {}
void print() { std::cout << "Base: a = " << a << '\n'; }
};
class A : public CloneCRTP<A, Base> {
private:
int b = 1;
public:
void print() { std::cout << "A: b = " << b << '\n'; }
};
Example:
int main() {
auto b = new Base();
auto b_clone = b->clone();
auto b_copy = b->copy();
b->print(); // Base print()
b_clone->print(); // Base print()
b_copy->print(); // Base print()
std::cout << "=========================\n";
auto a = new A();
auto a_clone = a->clone(); // returns Base*
auto a_copy = a->copy(); // returns A*
a->print(); // A print()
a_clone->print(); // Base print(), because clone returns pointer to the base class
a_copy->print(); // A print()
std::cout << "=========================\n";
auto c = static_cast<Base*>(a);
auto c_clone = c->clone(); // returns Base*, but A* inside
auto c_copy = c->copy(); // returns Base*, that is really Base
c->print(); // Base print()
c_clone->print(); // Base print()
c_copy->print(); // Base print()
std::cout << "=========================\n";
auto a_clone_restored = static_cast<A*>(c_clone);
auto a_copy_restored = static_cast<A*>(c_copy); // Invalid
a_clone_restored->print(); // A print()
a_copy_restored->print(); // A print()
delete b;
delete b_clone;
delete b_copy;
delete a;
delete a_clone;
delete a_copy;
return 0;
}
This approach allows to reuse crtp definition in all hierarchies that require clone functionality.
Code: https://coliru.stacked-crooked.com/a/269a2427fd2f919b
Is there a way to give an object the possibility to create new objects of it's own type, without specifying this type?
class Foo {
public:
virtual Foo* new_instance() {
return new type_of(this); // Some magic here
}
};
class Bar: public Foo {
};
Foo* a = new Foo();
Foo* b = new Bar();
Foo* c = a->new_instance();
Foo* d = b->new_instance();
I would now like c to be of type Foo, while d should be of type Bar.
Short answer: No, there is no way to make this magic happen.
You could use a macro to make overriding the function in subclasses easier, or create an intermediate class that uses the "curiously recurring template pattern":
template <typename T>
class FooDerived : public Foo
{
public:
T* new_instance() {
return new T();
}
};
class Bar : public FooDerived<Bar>
{
};
Foo* a = new Bar();
Foo* b = a->new_instance(); // b is of type Bar*
But this is most certainly not worth the effort.
Straightforward solution:
class Foo {
public:
virtual Foo* new_instance() {
return new Foo();
}
};
class Bar: public Foo {
public:
virtual Foo* new_instance() {
return new Bar();
}
};
You could use a Mixin to add a factory class. It seems rather complicated for a factory function and is certainly harder to comprehend.
#include <typeinfo>
#include <cassert>
#include <iostream>
template<class T> class WithFactory: public T {
public:
WithFactory<T>* new_instance() override {
return new WithFactory<T>( );
}
};
class FactoryFunction {
virtual FactoryFunction* new_instance() = 0;
};
class Foo_: public FactoryFunction {
public:
virtual void f() {
std::cout << "Foo" << std::endl;
}
};
typedef WithFactory<Foo_> Foo;
class Bar_: public Foo {
public:
virtual void f() override {
std::cout << "Bar" << std::endl;
}
};
typedef WithFactory<Bar_> Bar;
int main()
{
Foo* a = new Foo();
Foo* b = new Bar();
Foo* c = a->new_instance();
Foo* d = b->new_instance();
assert( typeid(a) == typeid(c) );
assert( typeid(b) == typeid(d) );
a->f();
b->f();
c->f();
d->f();
return 0;
}
Output is
Foo
Bar
Foo
Bar
Yes, you just have it do
virtual Foo* new_instance() { return new Foo(); }
And then in each derived class you overload it again to do the same (Although I much prefer the template approach to this sort of thing)