Pass Pointer of Cloned Class

Hi, I'm working to build a duplicated class, copying all data from the original class in, and passing a pointer to the new class to be used.

An example of it would be something to the effect of:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Foo
{
     int m_id;
     Foo *Clone();
     setID(int);

};

void Foo::setID(int id)
{
     m_id = id;
}

Foo Foo::*Clone()
{
     Foo *clone_ptr = new Foo();
     clone_ptr->setID(this->m_id); // Does not work. Why?
}


I understand that it's because it's a static member function, but I need to know how to go about doing this, and to be honest I'm at a complete loss.

Any suggestions?
Last edited on
Ok I got some help, and it seems like it was a syntax error.

line 14 should be
 
Foo *Foo::Clone()


And only then was I able to access the member variables.
Normally if you want to copy something, you just copy it.
 
std::string s = getstr();  // invokes the copy constructor 


However, if you have an interface, you really don't have the thing. And when you do somthing to it, you don't do it directly, but through the interface using virtual functions. However, when it comes to copying one, you need a virtual constructor. As C++ doesn't support this, the Clone Pattern is used for similar effect. For example:
1
2
3
4
Shape* s CopyShape(Shape* s)
{
    return s->Clone();
}


So it only makes sense to invoke the Clone Pattern if your object is part of an object hierachy. Otherwise don't use it.

Now, how we can fix your code. If your class is a standalone thing (an abstract data type), you just use the built in mechanisms, that is, a define a copy constuctor and assignment operator. And as your class doesn't hold pointers to things, the default implementation should suffice.
1
2
3
4
5
6
7
class Foo
{
    int m_id;

public:
    void setID(int  id) { m_id = id; }
};
You don't need clone on this.

Now, if Foo was part of a hierarchy, we're back to using Clone.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Base
{
public:
        virtual ~Base() = 0;
        virtual Base* Clone() = 0;
};

Base::~Base()
{
}

class Foo : public Base
{
        int m_id;

public:
        void setID(int  id) { m_id = id; }

        Foo() : m_id(0) {}
        ~Foo() {}
        Base* Clone() { return new Foo(*this); }  // use copy constructor for concrete instance
};

> ... You don't need clone on this.
> Now, if Foo was part of a hierarchy, we're back to using Clone.

We could let the compiler figure out what is the right thing to do for a particular type.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <functional>
#include <type_traits>

struct cloneable
{
    virtual ~cloneable() {}
    virtual cloneable* clone() const = 0 ;
};

template < typename T > inline
typename std::enable_if< std::is_base_of< cloneable, T >::value, T* >::type
clone( const T* p ) { return p ? static_cast<T*>( p->clone() ) : nullptr ; }

template < typename T > inline
typename std::enable_if< !std::is_base_of< cloneable, T >::value, T* >::type
clone( const T* p ) { return p ? new T(*p) : nullptr ; }

struct foo : cloneable
{
    virtual foo* clone() const override
    { std::cout << "foo* foo::clone() const override\n" ; /* clone */ return nullptr ; }
};

struct bar // not cloneable
{
    bar() = default ;
    bar( const bar& ) { std::cout << "bar::copy_constructor\n" ; /* copy */ }
};

int main()
{
   foo* a = new foo ;
   foo* b = clone(a) ; // foo* foo::clone() const override

   bar* c = new bar ;
   bar* d = clone(c) ; // bar::copy_constructor
}
Except that if it is not "cloneable", you may not want to return a pointer but an object.
Same if you are not using the hierarchy.
> Except that if it is not "cloneable", you may not want to return a pointer but an object.

Right. So, add one more overload of clone:
1
2
3
template < typename T > inline
typename std::enable_if< !std::is_base_of< cloneable, T >::value, T >::type
clone( const T& object ) { return T(object) ; }
Topic archived. No new replies allowed.