| FAQ | Newsboard | Telnet | Email TA | Lectures | Assignments | Man pages | Help |
|---|
class NewType {
public:
void Func(int n);
.
.
.
NewType(int JarUnits); // Constructor
private:
float privateFloat;
JarType privateJar;
};
Note that
void NewType::Func(int n)
{
privateJar.Add(n);
if(privateJar.Quantity() > 50)
privateFloat = 3.4 * float(n);
}
Now how do we initialize
NewType someObject(20);Where we want to initialize
C++ has Constructor Initializer Lists just for this purpose. A constructor initializer list is used whenever a class constructor needs to pass a parameter to a member's constructor.
Here is
NewType::NewType(int jarUnits) : privateJar(jarUnits)
{
privateFloat = 0.0;
}
When a class instance is created, its constructor body is executed
after all constructors for its members have been executed. Thus
when a
Here are a couple of rules that C++ enforces for constructor initializer lists.
class MyClass{
public:
.
.
.
MyClass(int n); // Constructor
private:
int privateVal;
YourClass alpha;
TheirClass beta;
};
assuming that YourClass and TheirClass have parametrized constructors, then
in the definition of MyClass's constructor, the constructor initializer list
requires a comma to separate the class to member constructors.
MyClass::MyClass(int n) : alpha(n), beta(n+5)
{
privateVal = n;
}
The order of constructors in the constructor initializer list does not
matter, it is the order of declaration of
So far we have looked at members and functions that use only one class instance
as an operand.
JarType jar1, jar2; jar1.Add(34);
We may for example want to be able to write
if (Equal(jar1, jar2)) DoSomething();The C++
class JarType {
public:
.
.
.
Boolean Equal(JarType otherJar) const;
//POST: FCTVAL == (This jar and otherJar contain
// the same number of of units
.
.
.
private:
int numUnits;
};
Clients must use the dot (.) notation to refer to
if (jar1.Equal(jar2))
.
.
.
and
Boolean JarType::Equal(JarType otherJar) const
{
return (numUnits == otherJar.numUnits);
}
However most programmers would prefer a more traditional way of writing
code
if (Equal(jar1, jar2))
.
.
.
In this case Equal could not be a member of JarType because
the function is not accessed using dot notation. On the other hand, if
Equal is not a member, it cannot access numUnits since
numUnits is a private member of JarType .
There is a way out of this catch-22. A class may grant permission to
a nonmember function to access its private members by declaring that
function to a friend of the class. A friend specification looks like
class SomeClass {
public:
.
.
.
friend SomeType SomeFunc(....);
private:
.
};
The scope of a friend function is that of the code surrounding the class
declaration. A client doesn't need to use dot notation to invoke friends.
Here's the specification file for JarType declaring Equal
a friend.
class JarType {
public:
.
.
.
friend Boolean Equal(JarType firstJar, JarType secondJar);
.
.
private:
int numUnits;
};
Here's Equal 's definition.
Boolean Equal(JarType firstJar, JarType secondJar)
{
return (firstJar.numUnits == secondJar.numUnits);
}
Note that Equal , a friend, is able to access private members of
the class that declared it as a friend.
A client could then use Equal as follows
jar1.Add(25);
cin >> someInt;
jar2.Add(somInt);
if(Equal(jar1, jar2))
DoSomething();
Friends provide a more traditional syntax for functions/operators that use two
or more instances of a class.
Operator Overloading
An overloaded operator can have more than one meaning depending
on the data types of its operands. Consider the specification of a member
Sum of SomeClass which returns a class instance
representing the sum of two other class instances.
SomeClass Sum(SomeClass ob1, SomeClass ob2);
We can overload the + operator to do the same thing. The only
thing that needs changing is the name of the member Sum . The notation
for overloading an operator is
operator
Thus to overload + to have the same meaning as the member
Sum , we write:
SomeClass operator<+>(SomeClass ob1, SomeClass ob2);
Clients can invoke this operator in two ways:
-
obj3 = operator+(obj1, obj2)
or
-
obj3 = obj1 + obj2
The second notation is just what we were after. If we overload the ==
operator to replace Equal job as a member to provide an
even "better" syntax.
class JarType {
public:
.
.
.
Boolean operator<==> (JarType otherJar);
//POST: FCTVAL == (This jar and otherJar contain
// the same number of of units
.
private:
.
};
We only need to replace the name Equal with the operator<==>
in the definition of the member function Equal .
Boolean JarType::operator<==>(JarType otherJar) const
{
return (numUnits == otherJar.numUnits);
}
Guidelines for operators overloading
- All C++ operators may be overloaded except the following four operators
::
.
sizeof
?:
- Overloading is allowed only if at least one operand is a class instance.
For example:
You cannot overload an operator to take two
ints as operands.
- It is impossible to
- change the standard precedence of operators.
- define new operator symbols not already in the C++ language.
- change the number of operands of an operator
- Overloading unary operators.
Let a be of type SomeClass , and we want to overload the unary minus operator(-), Then the expression
-a
is equivalent to the function invocation
-
a.operator-() if operator- is a member function.
-
operator-(a) if operator- is a friend.
- Overloading binary operators.
Let a be of type SomeClass , and suppose b is of
type AnyType and we want to overload the binary addition operator
(+), Then the expression
a + b
is equivalent to the function invocation
-
a.operator+(b) if operator+ is a member function.
-
operator+(a, b) if operator+ is a friend.
- Overloading
++ requires client code to sue pre-increment form
++someObject . Same for --
- Special rules apply to overloading the
=, (), [] . One restriction
is that the operator functions must be class members, not friends
- Many meanings for an operator can co-exist, as long as the compiler can
distinguish among the data types of the operands.