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 caseEqual could not be a member ofJarType because the function is not accessed using dot notation. On the other hand, ifEqual is not a member, it cannot accessnumUnits sincenumUnits is a private member ofJarType .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 declaringEqual a friend.class JarType { public: . . . friend Boolean Equal(JarType firstJar, JarType secondJar); . . private: int numUnits; };Here'sEqual 's definition.Boolean Equal(JarType firstJar, JarType secondJar) { return (firstJar.numUnits == secondJar.numUnits); }Note thatEqual , a friend, is able to access private members of the class that declared it as a friend.A client could then use
Equal as followsjar1.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 ofSomeClass 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 memberSum . The notation for overloading an operator is
operator Thus to overload
+ to have the same meaning as the memberSum , we write:SomeClass operator<+>(SomeClass ob1, SomeClass ob2);Clients can invoke this operator in two ways:The second notation is just what we were after. If we overload the
obj3 = operator+(obj1, obj2) or
obj3 = obj1 + obj2 == operator to replaceEqual 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 nameEqual with theoperator<==> in the definition of the member functionEqual .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.
Leta be of typeSomeClass , and we want to overload the unary minus operator(-), Then the expression-ais equivalent to the function invocation
a.operator-() ifoperator- is a member function.operator-(a) ifoperator- is a friend.- Overloading binary operators.
Leta be of typeSomeClass , and supposeb is of typeAnyType and we want to overload the binary addition operator (+), Then the expressiona + bis equivalent to the function invocation
a.operator+(b) ifoperator+ is a member function.operator+(a, b) ifoperator+ 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.