Files
CSCI-1200/lectures/04_classes_II/README.md
2025-01-20 19:48:59 -05:00

11 KiB

Lecture 4 --- Classes II: Copy Constructor, Assignment Operator, Destructor, and Non-member Operators

4.1 Copy Constructor

  • A copy constructor is a constructor which is used to create a new object as a copy of an existing object of the same class.
  • Copy constructors get called when you create a new object by copying an existing object using the assignment operator (=), or when you pass an object by value to a function.

Copy Constructor Syntax

ClassName(const ClassName& other);

Copy Constructor Example

#include <iostream>

class MyClass {
private:
    int value;

public:
    // Constructor
    MyClass(int val) : value(val) {}

    // Copy Constructor
    MyClass(const MyClass& other) {
        value = other.value;
        std::cout << "Copy Constructor Called!" << std::endl;
    }

    void display() const {
        std::cout << "Value: " << value << std::endl;
    }
};

int main() {
    MyClass obj1(10);
    MyClass obj2 = obj1; // Copy constructor is called here

    obj2.display(); // Output: Value: 10
    return 0;
}

4.2 Assignment Operator

  • The assignment operator (=) is used to copy the values from one object to another after both objects have been created.

Assignment Operator Syntax:

ClassName& operator=(const ClassName& other);

Assignment Operator Example:

#include <iostream>
#include <string>
using namespace std;

class MyClass {
private:
    string name; // Using a standard string (no pointers)
public:
    MyClass(const string& initName) : name(initName) {}

    MyClass& operator=(const MyClass& other) {
        name = other.name; // Copy data
        return *this;
    }

    void print() const { cout << "Name: " << name << endl; }
};

int main() {
    MyClass obj1("Object1");
    MyClass obj2("Object2");

    obj1 = obj2; // Assignment operator invoked
    obj1.print(); // Output: Name: Object2
    return 0;
}

All C++ class objects have a special pointer defined called this which simply points to the current class object, and the expression *this is a reference to the class object.

Assignment operators of the form:

obj1 = obj2;

are translated by the compiler as:

obj1.operator=(obj2);
  • Cascaded assignment operators of the form:
obj1 = obj2 = obj3;

are translated by the compiler as:

obj1.operator=(obj2.operator=(obj3));
  • Therefore, the value of the assignment operator (obj2 = obj3) must be suitable for input to a second assignment operator. This in turn means the result of an assignment operator ought to be a reference to an object.

Note: In C++, the assignment operator is used for assignment after an object has already been created. And because of that, the following two code snippets behave differently.

myClass A = B;

This one line will invoke the copy constructor, rather than the assignment operator. And this behavior is called copy initialization.

myClass A;
A = B;

These two lines will: the first line creates the object A, and the second line invokes the assignment operator.

4.3 Destructor (the “constructor with a tilde/twiddle”)

A destructor is a special member function automatically called when an object goes out of scope or is explicitly deleted.

Destructor Syntax

~ClassName();

Destructor Example

#include <iostream>
using namespace std;

class MyClass {
public:
    MyClass() { cout << "Constructor called\n"; }
    ~MyClass() { cout << "Destructor called\n"; }
};

int main() {
    MyClass obj; // Constructor called
    // Destructor will be called automatically at the end of scope
    return 0;
}

4.4 Overloading operator<< in C++

Purpose

The operator<< is commonly overloaded to enable custom objects to be output using streams such as std::cout.

Example

#include <iostream>
#include <string>

class Person {
private:
    std::string name;
    int age;

public:
    // Constructor
    Person(const std::string& name, int age) : name(name), age(age) {}

    // Public getters
    std::string getName() const { return name; }
    int getAge() const { return age; }
};

// Non-member function
std::ostream& operator<<(std::ostream& os, const Person& person) {
    os << "Name: " << person.getName() << ", Age: " << person.getAge();
    return os;
}

int main() {
    Person p("Alice", 30);
    std::cout << p << std::endl; // Output: Name: Alice, Age: 30
    return 0;
}

Question: Can we overload this operator as a member function?

4.5 Exercises