9.4 KiB
Lecture 4 --- Classes II: Sort, Non-member Operators
- Classes in C++;
- Non-member operators
4.1 C++ Classes
-
Nuances to remember
- Within class scope (within the code of a member function) member variables and member functions of that class may be accessed without providing the name of the class object.
- Within a member function, when an object of the same class type has been passed as an argument, direct access to the private member variables of that object is allowed (using the ’.’ notation).
4.2 Operator Overloading
- When sorting objects of a custom class, we can provide a third argument to the sort function, and this third argument is a comparison function.
- What if we do not want to provide this third argument? The answer is: define a function that creates a < operator for objects of that class! At first, this seems a bit weird, but it is extremely useful.
- Let’s start with syntax. The expressions a < b and x + y are really function calls! Syntactically, they are equivalent to operator< (a, b) and operator+ (x, y) respectively.
- When we want to write our own operators, we write them as functions with these weird names.
- For example, if we write:
bool operator< (const Date& a, const Date& b) {
return (a.getYear() < b.getYear() ||
(a.getYear() == b.getYear() && a.getMonth() < b.getMonth()) ||
(a.getYear() == b.getYear() && a.getMonth() == b.getMonth() && a.getDay() < b.getDay()));
}
then the statement
sort(dates.begin(), dates.end());
will sort Date objects into chronological order.
- Really, the only weird thing about operators is their syntax.
- We will have many opportunities to write operators throughout this course. Sometimes these will be made class member functions, but more on this in a later lecture.
4.3 Questions
- Can you solve leetcode problem 905 with an overloaded operator <, and make this overloaded operator < a non-member function?
- Can you solve leetcode problem 905 with an overloaded operator <, and make this overloaded operator < a member function?
- Can you solve leetcode problem 905 with an overloaded operator <, and make this overloaded operator < a member function, plus make the definition of this member function outside of the class definition?
4.4 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 are automatically generated by the compiler if you do not provide one explicitly. However, if your class uses dynamic memory (which will be covered in next lecture), and you want a copy constructor, then you must write your own copy constructor.
- 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.
- Still use the Date class as an example, if you have defined your own copy constructor whose prototype is like:
Date(const Date &other);
and when you have the following lines of code:
Date a;
Date b = a;
The first statement will call the default constructor, while the second statement will call the copy constructor.
4.5 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.6 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;
}