March 24 notes:
Copy constructors:
In C++ there's a special case for constructors: the copy
constructor. The idea of this one is that it allows you to set a
new instance of an object to the value of an existing object. The
prototype of such a constructor (in a .h file) would be as follows:
classname(const classname& existinginstance);
The body of the copy constructor would simply copy over all of the
properties (ie: variables) from the instance passed as an argument into
the local copies.
For instance if you have an int named data, you would need the
following line inside of the method:
data = existinginstance.data;
What's special about this form of the constructor is that it is called
when you run the 2nd of these two lines of code:
classname myclass1;
classname myclass2 = myclass1;
Note: this will ONLY be envoked on lines where you are declaring an
instance of a class, if you want a general copy method that works with
the = sign, look below to operator overloading.
const:
const is a keyword built into C++ which indicates a variable that
should not be modified. It will basically assert that no changes
are allowed to be made. For instance, if you are writing a
function to search through an apvector, there's no real need to modify
the values of the apvector, and thus you should probably declare the
apvector argument as const. In reality, this is just another way
of saving the world from sloppy programming, but it's something the AP
people want you to know, and want you to use when appropriate, so get
used to using const on any argument that should not be changed, or on
any return value that should not be altered.
Operator overloading:
C++ has many confusing features that gain you very little, but it also
has a handful of confusing features which can be kind of neat.
One of these is the idea of operator overloading. Up until now in
order to manipulate classes you write you have to manually tell C++ to
run a specific method. C++ also allows you to overload all of the
built in operators to treat them as special kinds of methods for your
classes and thus can make your classes look like they are a part of
C++'s built in data types!
The format for a method that can overload an operator in the class
definition is as follows:
returntype operator {operator} (arguments) where {operator} is replaced
with the operator you are overloading.
For instance, if you want to overload the assignment operator (to make
copying easier) you could write the following:
const myclass& operator =(const myclass&
rhs);
it returns a reference to myclass because the assignment operator
actually returns a copy of the value the left hand-side of the operator
is set to.
For instance if I say cout << (myint = 2 *6), that will print out
12
the rhs argument will be the instance of the class on the right hand
side. (rhs = right hand side)
So if I have 2 instances of myclass, one names mc1, the other named
mc2, and I type the following:
mc1 = mc2;
this is equivilent to writing
mc1.operator =(mc2);
(assuming we could directly run that method like that. We
actually can't since operator overloading is a very special case in C++)
The implementation of this method could look like this:
const myclass& myclass::operator =(const myclass &rhs) {
data = rhs.data; // just copy over all of the data
you need to
return *this;
}
The last line looks very very odd. It will make more sense when
you get into pointers and linked lists, but for right now, whenever you
overload an operator and need to return a reference to the current
instance of the class, you just need to say return *this, so for now
just memorize this special case.
Note: not all operators should return instances of the same
class. For instance, the == operator will normally return a bool
If you wanted to implement a == overload, you could use the following
in your .h file
bool operator ==(const myclass &rhs);
while its implementation could look like this:
bool myclass::operator ==(const myclass &rhs) {
return (data == rhs.data);
}
and this would be envoked by saying
if(mc1 == mc2)
In addition, you can get polymorphic with operator overloading!
(joy!)
Let's say you want to be able to add integers into your myclass
directly:
you could write the following in your class definition:
const myclass& operator +=(const int rhs);
The implementation could look like this:
const myclass& myclass::operator +=(const int rhs) {
data += rhs;
return *this;
}
and you can do this even if you already have another += operator
defined that takes in another instance of myclass; C++ will decide
which to call depending on if you pass in an integer or a instance of
myclass.
For instance, if you say mc1 += 3, C++ knows to go for the one that
takes an int as the argument, and if you say mc1 += mc2 it will look
for the one that takes an instance of myclass as an argument.
Wasn't that fun??