610 likes | 674 Views
Learn about friend functions, how to declare them, and their usage in C++ programming. Explore the concept of friends, separate compilation, namespaces, header and implementation files, and more. Utilize friend functions to access private data from multiple classes efficiently.
E N D
Lecture 6 Friends and Namespace COSC 1567 C++ Programming
Objectives • What a friend is • Declare a friend function • Use a friend function with data from two classes • Use a forward reference • Use a friend function with two or more instances of the same class • bestow friendship on functions that are members of other classes • Bestow friendship on an entire class
Objectives • Separate Compilation • Encapsulation reviewed • Header and implementation files • Namespaces • using directives • Qualifying names • Unnamed namespaces • Hiding helping functions • Nested namespaces
What Are Friends? • A friend function is a function that can access private data members of a class, even though the function itself is not a member of the class • A friend class is a class whose functions can all access private data members of another class • A friend function can access private data from a class of which it is not a member, but a friend function cannot be a friend on its own • The friend relationship is always one-sided
Friend Functions • Nonmember functions • Recall: operator overloads as nonmembers • They access data through accessor and mutatorfunctions • Very inefficient (overhead of calls) • Friends can directly access private class data • No overhead, more efficient • So: best to make nonmember operatoroverloads friends!
Friend Functions • Friend function of a class • Not a member function • Has direct access to private members • Just as member functions do • Use keyword friend in front of function declaration • Specified IN class definition • But they’re NOT member functions!
How to Declare a Function as a Friend • The class contains data fields for a customer number and balance • The class contains three functions; two are members of the class • The default constructor for the Customer class supplies values for the data fields if none are provided when a Customer object is instantiated
How to Declare a Function as a Friend • As a member of the Customer class, the displayCustomer() function meets the following conditions: • Requires the class name Customer and the scope resolution operator in the function header • Must have access to the private fields custNum and balanceDue • Must be declared in the public section of the class definition, so that a main() program (or any other client function) can use it
How to Declare a Function as a Friend • The function displayAsAFriend() is not a Customer member function • It must meet the following conditions: • Cannot use the class name Customer and the scope resolution operator in the function header • Need not be declared in the public section of the class definition • Must use the C++ keyword friend in its declaration
How to Declare a Function as a Friend • When any function tries to access an object’s private data member, the compiler examines the list of function prototypes in the class declaration, and one of three things happens: • The function is found to be a member function, and access is approved • The function is found to be a friend function, and access is approved • The function is not found to be a member or a friend, and access is denied; you receive an error message
Using a Friend Function to Access Data from Two Classes • Figure 7-3 shows the definition section of a CustTransaction class • You might create a CustTransaction object for each customer transaction, such as a purchase of an item, payment on an account, or return of an item
Using a Friend Function to Access Data from Two Classes • If you create a function that performs the payment application operation, you have at least five choices (although four of these are inferior choices): • You can make the balanceDue field in the Customer class public, and the paymentAmount field in the CustTransaction class public • If you create a payment application function that is not a member of either the Customer or the CustTransaction class, the function will not have access to the private data fields of either class
Using a Friend Function to Access Data from Two Classes • The choices continued: • If you make the payment application function a member of the Customer class, the function has access to balanceDue, but not to paymentAmount, which is private within the CustTransaction class • If you make the payment application function a member of the CustTransaction class, the function has access to paymentAmount, but not to balanceDue, which is private within the Customer class • You can make the payment application function a friend of both classes
Friend Function Uses • Operator Overloads • Most common use of friends • Improves efficiency • Avoids need to call accessor/mutatormember functions • Operator must have access anyway • Might as well give full access as friend • Friends can be any function
Friend Function Purity • Friends not pure? • "Spirit" of OOP dictates all operators and functions be member functions • Friends violate basic OOP principles • Advantageous? • For operators: very! • Allows automatic type conversion • Still encapsulates: friend is in class definition • Improves efficiency
Using a Forward Reference • To use the applyTransaction() function as a friend to both the Customer and the CustTransaction class, you must declare the function as a friend within each class • The declaration of the applyTransaction() function is: friend void applyTransaction(Customer cust, CustTransaction trans); • You already know you must declare a variable before using it
Using a Forward Reference • You also must declare, or prototype, a function before you use it • Similarly, a class must be declared before you use it • A forward reference lets the compiler know that the class exists, and that the details will come later
Using a Friend Function with Two Classes Ex6-2.cpp
Using a Forward Reference • When two classes refer to each other, you can choose to forward declare either one, and then define the other class first • The same principle holds true if three, four, or more classes share a friend function that makes reference to all the classes
Using a Forward Reference • In this case you: • Forward declare all the classes except one • Define the class you did not forward declare, and include the friend function prototype in the class definition • Define all classes that you did forward declare. The forward declared classes will contain the same friend function prototype as the first class you defined • Define the friend function itself Ex6-3
Two Instances of a Class Using a Friend • You can use a friend function to access private data members from objects that belong to two different classes • If you want a function to have access to two or more instances of the same class, you can use either a class member function or a friend function • You can sum two CustTransaction objects without creating a friend function
Two Instances of a Class Using a Friend • You simply create a member function for the CustTransaction class • The prototype is: CustTransaction addTransactions (const CustTransaction aPayment);
CustTransaction Class with addTransactions() Member Function Ex6-4.cpp
Two Instances of a Class Using a Friend • Within addTransactions(), the billingSummary.paymentAmount is set equal to the sum of the invoking object’s (firstTrans) paymentAmount and the passed object’s (secondTrans) payment amount • A copy of the entire, newly constructed and defined billingSummary is returned to the calling function, where totalTrans receives it • One way to avoid a subsidiary transaction is to create a friend function to the CustTransaction class
CustTransaction Class a Friend Function Ex6-5.cpp
Two Instances of a Class Using a Friend • Another example • Create a friend function to compare two Loan objects and determine whether they are equal • Consider two loans equal if they are for the same amount at the same interest rate Ex6-6.cpp
Making a Friend of a Member of Another Class • Classes can bestow friendship on nonmember functions; they also can bestow friendship on functions that are members of other classes • Consider two classes developed for a college registration system • One class is named StudentRequest; it holds a student idNum and a course section in which the student requests enrollment • The other class, named CourseRec, holds information about one section of a course, including a section number, enrollment limit, and current enrollment
Making a Friend of a Member of Another Class • The student enrollment request example shows a class granting friendship to a single function that is a member of another class • Creating the class definitions for the preceding example requires three operations: • Forward declare the class that is granting friendship, because the class that holds the friend will use this class name • Declare the class containing the function that will be a friend • Define the class that is granting friendship
Making a Friend of a Member of Another Class • Another example: • Two classes of objects are needed: Courses and Rooms • When a Course section is scheduled, a search is made for a Room that holds the number of students that might enroll Ex6-8.cpp
Making a Friend of Another Class • To grant friendship to an entire class, construct the class definition simply by writing the keyword friend followed by class and the name of the class • When you grant friendship to a class, every function that is a member of the class becomes a friend of the granting class Modify ex6-7.cpp
Friend Classes • Entire classes can be friends • Similar to function being friend to class • Example:class F is friend of class C • All class F member functions are friends of C • NOT reciprocated • Friendship granted, not taken • Syntax: friend class F • Goes inside class definition of "authorizing" class
Separate Compilation • Program Parts • Kept in separate files • Compiled separately • Linked together before program runs • Class definitions • Separate from "using" programs • Build library of classes • Re-used by many different programs • Just like predefined libraries
Class Separation • Class Independence • Separate class definition/specification • Called "interface" • Separate class implementation • Place in two files • If implementation changes only thatfile need be changed • Class specification need not change • "User" programs need not change
Encapsulation Reviewed • Encapsulation principle: • Separate how class is used by programmerfrom details of class’s implementation • "Complete" separation • Change to implementation NO impact onany other programs • Basic OOP principle
Encapsulation Rules • Rules to ensure separation: • All member variables should be private • Basic class operations should be: • Public member functions • Friend or ordinary functions • Overloaded operators Group class definition and prototypes together • Called "interface" for class • Make class implementation unavailable tousers of class
Namespaces • Namespace defined:A collection of name definitions • Class definitions • Variable declarations • Programs use many classes, functions • Commonly have same names • Namespaces deal with this • Can be "on" or "off" • If names might conflict turn off
using Directive • using namespace std; • Makes all definitions in std namespaceavailable • Why might you NOT want this? • Can make cout, cin have non-standardmeaning • Perhaps a need to redefine cout, cin • Can redefine any others
Namespace std • We’ve used namespace std • Contains all names defined in many standard library files • Example:#include <iostream> • Places all name definitions (cin, cout, etc.)into std namespace • Program doesn’t know names • Must specify this namespace for programto access names
Global Namespace • All code goes in some namespace • Unless specified global namespace • No need for using directive • Global namespace always available • Implied "automatic" using directive
Multiple Names • Multiple namespaces • e.g., global, and std typically used • What if name defined in both? • Error • Can still use both namespaces • Must specify which namespace used atwhat time
Specifying Namespaces • Given namespaces NS1, NS2 • Both have void function myFunction()defined differently { using namespace NS1; myFunction();}{ using namespace NS2; myFunction();} • using directive has block-scope
Creating a Namespace • Use namespace grouping:namespace Name_Space_Name{ Some_Code} • Places all names defined in Some_Codeinto namespace Name_Space_Name • Can then be made available:using namespace Name_Space_Name
Creating a Namespace Example Ex6-9.cpp • Function declaration:namespace Space1{ void greeting();} • Function definition:namespace Space1{ void greeting() { cout << "Hello from namespace Space1.\n"; }}