How to write a clone method easily? - c++

I have a base class with a virtual clone new method
class A
{
virtual A* cloneNew() const { return new A; }
};
and its derivatives
class A1 : public A
{
virtual A1* cloneNew() const { return new A1; }
};
class A2 : public A
{
virtual A2* cloneNew() const { return new A2; }
};
Now I want to use macro or other way to make its re-implementation more easily like
class A1: public A
{
CLONE_NEW; // no type A1 here
};
Is it possible to do it? Does decltype(this) help?

The following works fine for me, and can easily be turned into a macro:
struct Foo
{
virtual auto clone() -> decltype(this)
{
return new auto(*this);
}
};
If you want the clone() function to be const, you cannot use new auto and you have to work a bit harder with the return type:
#include <type_traits>
virtual auto clone() const -> std::decay<decltype(*this)>::type *
{
return new std::decay<decltype(*this)>::type(*this);
}

Related

Copy an abstract class without modifying it

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

ensure class member variables are not modified when cloning

I am trying to add a clone func for class A. This class has a non const and not owned pointer b_. I want to make sure that b_ wont be modified in the cloned objects, but it is ok to modify other member variables, and these non-const func in A can still be called.
A bad way is adding a flag and check it every time before modifying b_. It is bad because if a new func in A is added, some one else might forget to check it.
Is there a better way to achieve this goal?
Here is my bad solution mentioned above:
class A {
public:
A* clone() const {
auto* clone = new A(*this);
clone->is_cloned_ = true;
return clone;
}
void DoSomething() {
if (!is_cloned_){
b_->NonConstFunc();
}
}
void DoSomethingElse() {
other_values = 2; // cloned versions can modify this.
}
private:
is_cloned_ = false;
B* b_; // Not owned
int other_values = 1;
}
You could perhaps design a class hierarchy like this:
class cloned_A;
class A
{
public:
cloned_A *clone ();
private:
B* b_;
};
class cloned_A : public A
{
public:
cloned_A (const B *b) : read_only_b (b) {}
private:
const B* read_only_b;
};
cloned_A *A::clone ()
{
return new cloned_A (b_);
}
Now b_ is private to A and the cloned object can only access read_only_b via a const pointer and therefore cannot modify it.
A way to avoid issue when adding method to A is to wrap the logic to access B in its own class:
class ProtectedB
{
public:
ProtectedB(B& b) : b(&b) {}
ProtectedB(const ProtectedB& rhs) : b(rhs.b), cloned(true) {}
// Duplicate public B interface
void NonConstFunc() {
if (cloned){ return; }
b->NonConstFunc();
}
// Possibly (might avoid to duplicate non mutable interface of B)
const B& GetB() const { return *b; };
private:
B* b = nullptr;
bool cloned = false;
};
Then A is simply:
class A {
public:
// ...
std::unique_ptr<A> clone() const { return std::make_unique<A>(*this); }
void DoSomething() { b.NonConstFunc(); }
void DoSomethingElse() { other_values = 2; } // cloned versions can modify this.
private:
ProtectedB b;
int other_values = 1;
};

c++ how to implement a switch between class members

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();
}

c++ design query

I am designing a framework in c++ which is supposed to provide basic functionality and act as interface for the other derived systems.
#include <stdio.h>
class Module
{
public:
virtual void print()
{
printf("Inside print of Module\n");
}
};
class ModuleAlpha : public Module
{
public:
void print()
{
printf("Inside print of ModuleAlpha\n");
}
void module_alpha_function() /* local function of this class */
{
printf("Inside module_alpha_function\n");
}
};
class System
{
public:
virtual void create_module(){}
protected:
class Module * module_obj;
};
class SystemAlpha: public System
{
public:
void create_module()
{
module_obj = new ModuleAlpha();
module_obj->print(); // virtual function, so its fine.
/* to call module_alpha_function, dynamic_cast is required,
* Is this a good practice or there is some better way to design such a system */
ModuleAlpha * module_alpha_obj = dynamic_cast<ModuleAlpha*>(module_obj);
module_alpha_obj->module_alpha_function();
}
};
main()
{
System * system_obj = new SystemAlpha();
system_obj->create_module();
}
Edited the code to be more logical and it compiles straight away. The question is, that is there a better way to design such a system, or dynamic_cast is the only solution. Also, if there are more derived modules, then for type-casting, there is some intelligence required in the base Module class.
If Derived is the only concrete instance of Base you could use static_cast instead.
Personally, I define a function, like MyCast for every specialized class. I define four overloaded variants, so that I can down-cast const and non-const pointers and references. For example:
inline Derived * MyCast(Base * x) { return static_cast<Derived *> (x); }
inline Derived const * MyCast(Base const * x) { return static_cast<Derived const *>(x); }
inline Derived & MyCast(Base & x) { return static_cast<Derived &> (x); }
inline Derived const & MyCast(Base const & x) { return static_cast<Derived const &>(x); }
And likewise for Derived2 and Base2.
The big advantage in having all four is that you will not change constness by accident, and you can use the same construct regardless if you have a pointer or a reference.
Of course, you could replace static_cast with a macro, and use dynamic_cast in debug mode and static_cast is release mode.
Also, the code above can easily be wrapped into a macro, making it easy to batch-define the functions.
Using this pattern, you could then implement your code as:
class Derived : public Base
{
public:
virtual void func2()
{
base2_obj = new Derived2();
}
void DerivedFunc()
{
MyCast(base2_obj)->Derived2Func();
}
}
The design gets much cleaner if Base does not contain the base_obj object, but rather gets a reference via a virtual method. Derived should contain a Derived2 object, like:
class Base
{
public:
virtual void func1();
private:
class Base2;
virtual Base2& get_base2();
};
class Derived : public Base
{
Derived2 derived2;
public:
Base2& get_base2() { return derived2; }
void DerivedFunc()
{
derived2->Derived2Func();
}
}
If you are worried about performance, pass the reference in the constructor of Base.
I took your code with its many compile errors and tried to simplify it. Is this what you are trying to acheive? It will compile.
class Base2 {
public:
virtual void Derived2Func(){
}
};
Base2* fnToInstantiateABase2();
class Base {
public:
Base() : base2_obj(fnToInstantiateABase2()) {
}
virtual void DerivedFunc() {
}
protected:
Base2* base2_obj;
};
class Derived : public Base {
public:
void DerivedFunc() {
base2_obj->Derived2Func(); // not possible as base2_obj is of type Base2
}
};
class Derived2 : public Base2 {
public:
void Derived2Func() {
}
};
void test() {
Base * base_obj = new Derived();
base_obj->DerivedFunc();
}
Base2* fnToInstantiateABase2() {
return new Derived2();
}

Copy object - keep polymorphism

The following code tries to copy an object and keep the original type.
Unfortunately it does not work (every copied object will become a Super instead of being of the same class as its original).
Please note that copySuper(const Super& givenSuper) should not know anything about the subclasses of Super.
Is it possible to do such a copy? Or do I have to change the definition of copySuper ?
#include <string>
#include <iostream>
class Super
{
public:
Super() {};
virtual ~Super() {};
virtual std::string toString() const
{
return "I'm Super!";
}
};
class Special : public Super
{
public:
Special() {};
virtual ~Special() {};
virtual std::string toString() const
{
return "I'm Special!";
}
};
Super* copySuper(const Super& givenSuper)
{
Super* superCopy( new Super(givenSuper) );
return superCopy;
}
int main()
{
Special special;
std::cout << special.toString() << std::endl;
std::cout << "---" << std::endl;
Super* specialCopy = copySuper(special);
std::cout << specialCopy->toString() << std::endl;
return 0;
}
//Desired Output:
// # I'm Special!
// # ---
// # I'm Special!
//
//Actual Output:
// # I'm Sepcial!
// # ---
// # I'm Super!
Try this:
class Super
{
public:
Super();// regular ctor
Super(const Super& _rhs); // copy constructor
virtual Super* clone() const {return(new Super(*this));};
}; // eo class Super
class Special : public Super
{
public:
Special() : Super() {};
Special(const Special& _rhs) : Super(_rhs){};
virtual Special* clone() const {return(new Special(*this));};
}; // eo class Special
Note that we have implemented a clone() function that Special (and any other derivative of Super) overrides to create the correct copy.
e.g:
Super* s = new Super();
Super* s2 = s->clone(); // copy of s
Special* a = new Special();
Special* b = a->clone(); // copy of a
EDIT: As other commentator pointed out, *this, not this. That'll teach me to type quickly.
EDIT2: Another correction.
EDIT3: I really should not post so quickly when in the middle of work. Modified return-type of Special::clone() for covariant return-types.
This is what you need :
class Super
{
public:
Super()
{
}
virtual Super* clone() const
{
return( new Super(*this) );
};
};
class Special : public Super
{
public:
Special() : Super()
{
};
Special(const Special& _rhs) : Super(_rhs)
{
};
virtual Special* clone() const
{
return( new Special( *this ) );
};
};
int main()
{
Special a;
Super &c( a );
Super *b1 = c.clone();
Special *b2 = a.clone();
Super *b3 = a.clone();
}
One of previous examples has the clone for derived class wrong. The above is correct way of implementing the clone method.
What you want is generally implemented using an abstract clone method in the base class. Special will typically implement this method by returning new Special(*this).
Also note that it is considered a best practice to make base classes uncopyable.
Just for the record, this is in the C++ FAQ:
http://www.dietmar-kuehl.de/mirror/c++-faq/abcs.html#faq-22.5