35

I wrote a Stack and Queue implementation (Linked List based). There is one stack (bigStack). For example, I separate bigStack (example: stackA and stackB). I pop() a node from bigStack, I push() in stackA. In the same way, I push() in stackB. I want bigStack to not change. Therefore I want to clone the bigStack object. How do I clone objects in C++? Or is there another solution to my problem?

class Stack : public List {
public:
   Stack() {}
   Stack(const Stack& rhs) {}
   Stack& operator=(const Stack& rhs) {};
    ~Stack() {}

    int Top() {
        if (head == NULL) {
            cout << "Error: The stack is empty." << endl;
            return -1;
        } else {
            return head->nosu;
        }
    }

    void Push(int nosu, string adi, string soyadi, string bolumu) {
        InsertNode(0, nosu, adi, soyadi, bolumu);
    }

    int Pop() {
        if (head == NULL) {
            cout << "Error: The stack is empty." << endl;
            return -1;
        } else {
            int val = head->nosu;
            DeleteNode(val);
            return val;
        }
    }

    void DisplayStack(void);

};

then...

Stack copyStack = veriYapilariDersi;
copyStack.DisplayStack();
Grimeh
  • 161
  • 1
  • 12
mert
  • 920
  • 3
  • 15
  • 24

4 Answers4

45

The typical solution to this is to write your own function to clone an object. If you are able to provide copy constructors and copy assignement operators, this may be as far as you need to go.

class Foo
{ 
public:
  Foo();
  Foo(const Foo& rhs) { /* copy construction from rhs*/ }
  Foo& operator=(const Foo& rhs) {};
};

// ...

Foo orig;
Foo copy = orig;  // clones orig if implemented correctly

Sometimes it is beneficial to provide an explicit clone() method, especially for polymorphic classes.

class Interface
{
public:
  virtual Interface* clone() const = 0;
};

class Foo : public Interface
{
public:
  Interface* clone() const { return new Foo(*this); }
};

class Bar : public Interface
{
public:
  Interface* clone() const { return new Bar(*this); }
};


Interface* my_foo = /* somehow construct either a Foo or a Bar */;
Interface* copy = my_foo->clone();

EDIT: Since Stack has no member variables, there's nothing to do in the copy constructor or copy assignment operator to initialize Stack's members from the so-called "right hand side" (rhs). However, you still need to ensure that any base classes are given the opportunity to initialize their members.

You do this by calling the base class:

Stack(const Stack& rhs) 
: List(rhs)  // calls copy ctor of List class
{
}

Stack& operator=(const Stack& rhs) 
{
  List::operator=(rhs);
  return * this;
};
John Dibling
  • 99,718
  • 31
  • 186
  • 324
  • @drceng: You have to actually implement those functions. The code you're provided above does nothing in the methods. The code I posed here is really just psudocode. – John Dibling Oct 15 '12 at 20:07
  • I am confused.I code for hours.I didn't see,method isn't do anything :) Ok,I understand.But how to implement ? How to copy construction ? – mert Oct 15 '12 at 20:12
  • Does `Stack` really have no member variables? – John Dibling Oct 15 '12 at 20:15
  • Yes.It hasn't.Stack class friend List class. – mert Oct 15 '12 at 20:20
  • 1
    However note that even with non-polymorphic classes it is not typically necesarry to provide explicit copy constructors or copy assignment operators. The implicit (ie, compiler-provided default) constructor and operator are often sufficient to do the right thing. Since this means there is less code to get wrong, you should not implement these at all unless you actually need to. – John Dibling Oct 15 '12 at 20:31
  • 1
    @JohnDibling I agree for the most part, but whether or not the defaults provide the correct behavior is heavily dependent on proper use of RAII in the class' fields' types. In a code base that makes heavy use of raw pointers as fields, the default copy/assign will *almost never* do the right thing. This is one more great argument for proper use of RAII, but sometimes we get stuck maintaining less-than-ideal codebases. – WeirdlyCheezy Oct 16 '12 at 05:09
  • The second snippet I've found valuable. – Blue Print Apr 14 '22 at 18:08
3

In C++ copying the object means cloning. There is no any special cloning in the language.

As the standard suggests, after copying you should have 2 identical copies of the same object.

There are 2 types of copying: copy constructor when you create object on a non initialized space and copy operator where you need to release the old state of the object (that is expected to be valid) before setting the new state.

Kirill Kobelev
  • 10,252
  • 6
  • 30
  • 51
  • But my object is initaliazed.Stack is full.I want to clone stack with its nodes. – mert Oct 15 '12 at 20:26
  • I do not see data fields in your class. It is not clear what your `List` is. The info in incomplete. In general you need to copy your object, call same method in your base class. Element of your stack should also copyable. – Kirill Kobelev Oct 15 '12 at 20:44
2

If your object is not polymorphic (and a stack implementation likely isn't), then as per other answers here, what you want is the copy constructor. Please note that there are differences between copy construction and assignment in C++; if you want both behaviors (and the default versions don't fit your needs), you'll have to implement both functions.

If your object is polymorphic, then slicing can be an issue and you might need to jump through some extra hoops to do proper copying. Sometimes people use as virtual method called clone() as a helper for polymorphic copying.

Finally, note that getting copying and assignment right, if you need to replace the default versions, is actually quite difficult. It is usually better to set up your objects (via RAII) in such a way that the default versions of copy/assign do what you want them to do. I highly recommend you look at Meyer's Effective C++, especially at items 10,11,12.

WeirdlyCheezy
  • 704
  • 4
  • 4
0

  #include<iostream>
  using namespace std;
  class A{
      public:
      int id;
      A():id(0){}
      A(A &o){
       
       
         this->id=o.id;
    
     }
    
     
};

int main()
{
    A obj;
    A obj2=obj;
    obj2.id=1;
    A *ho1 =new A();
    A *ho2=new A(*ho1);//while allocating, new memory allocation is done. it creates a deep copy clone.
   // A *ho2=ho1;// this does not allocate memory and created shall clone
    ho2->id=22;
    cout<<obj.id<<endl;
    cout<<obj2.id<<endl;
    cout<<ho1->id<<endl;
    cout<<ho2->id<<endl;
}

the clone is created for object memory allocation using new as well as regular object creation.

  • Welcome to stackoverflow! This question is quite old, and the accepted answer already suggests the same thing as you do here, while being a bit more detailed and polished. The distinction between shallow and deep copy that you make here is also not quite correct (https://stackoverflow.com/questions/184710/what-is-the-difference-between-a-deep-copy-and-a-shallow-copy). A second pointer to the same object is not a shallow copy of the object itself. But no worries, maybe check out for some questions that don't have an answer yet instead? – ChrisB Mar 18 '23 at 17:54