现在的位置: 首页 > 综合 > 正文

C++读书笔记之友元 friend

2013年11月05日 ⁄ 综合 ⁄ 共 7665字 ⁄ 字号 评论关闭

A friend class in C++, can access the "private" and "protected" members of the class in which it is declared as a friend. On declaration of friend class all member function of the friend class become friends of
the class in which the friend class was declared. Friend status is not inherited; every friendship has to be explicitly declared. Friend classes can help in improving Encapsulation if used wisely.



Classes are declared as friends within the definition of the class who is giving access to others; this prevents a class from giving itself access to another's protected members, which enforcesencapsulation.
The friend class has the same level of access irrespective of whether the friend declaration appears in either the public, protected or private sections of the class definition. Friend status is granted by using thefriend keyword:

friend class ClassName;

Example

#include <iostream>
 
class B
{
    // B declares A as a friend...
    friend class A;
 
private:
    void privatePrint()
    {
        std::cout << "hello, world" << std::endl;
    }
};
 
class A
{
public:
    A()
    {
        B b;
        // ... and A now has access to B's private members
        b.privatePrint();
    }
};
 
int main()
{
    A a;
    return 0;
}

Advantages of using friend class

  • It provides additional functionality which is kept outside the class.
  • It provides functions with data which is not normally used by the class.
  • It provides a means of reducing algorithmic complexity by giving direct access to private and protected members to an external specified scope while not making the members more broadly accessible than necessary.

A friend function of a class is defined outside that class's scope but it has the right to access all private and protected members of the class. Even though the prototypes for friend functions appear in the class
definition, friends are not member functions.

A friend can be a function, function template, or member function, or a class or class template, in which case the entire class and all of its members are friends.

To declare a function as a friend of a class, precede the function prototype in the class definition with keywordfriend as follows:

class Box
{
   double width;
public:
   double length;
   friend void printWidth( Box box );
   void setWidth( double wid );
};

To declare all member functions of class ClassTwo as friends of class ClassOne, place a following declarationin the definition of class ClassOne:

friend class ClassTwo;

Consider the following program:

#include <iostream>
 
using namespace std;
 
class Box
{
   double width;
public:
   friend void printWidth( Box box );
   void setWidth( double wid );
};

// Member function definition
void Box::setWidth( double wid )
{
    width = wid;
}

// Note: printWidth() is not a member function of any class.
void printWidth( Box box )
{
   /* Because setWidth() is a friend of Box, it can
    directly access any member of this class */
   cout << "Width of box : " << box.width <<endl;
}
 
// Main function for the program
int main( )
{
   Box box;
 
   // set box width without member function
   box.setWidth(10.0);
   
   // Use friend function to print the wdith.
   printWidth( box );
 
   return 0;
}

When the above code is compiled and executed, it produces following result:

Width of box : 10


C++ provides the friend keyword to do just this. Inside a class, you canindicate that other classes (or simply functions) will have direct access toprotected and private members of the class. When granting access
to a class,you must specify that the access is granted for a class using the classkeyword:

friend class aClass;

Note that friend declarations can go in either the public, private,or protected section of a class--it doesn't matter where they appear. Inparticular, specifying a friend in the section marked protected doesn'tprevent
the friend from also accessing private fields.

Here is a more concrete example of declaring a friend:

class Node 
{
    private: 
    int data;
    int key;
    // ...

    friend class BinaryTree; // class BinaryTree can now access data directly
};

Now, Node does not need to provide any means of accessing the data stored inthe tree. The BinaryTree class that will use the data is the only class thatwill ever need access to the data or key. (The BinaryTree class
needs to usethe key to order the tree, and it will be the gateway through whichother classes can access data stored in any particular node.)

Now in the BinaryTree class, you can treat the key and data fields as thoughthey were public:

class BinaryTree
{
    private:
    Node *root;

    int find(int key);
};
int BinaryTree::find(int key)
{
    // check root for NULL...
    if(root->key == key)
    {
        // no need to go through an accessor function
        return root->data;
    }
    // perform rest of find

Friend Functions

Similarly, a class can grant access to its internal variables on a moreselective basis--for instance, restricting access to only a single function.To do so, the entire function signature must be replicated after the
friendspecifier, including the return type of the function--and, of course, you'llneed to give the scope of the function if it's inside another class:

friend return_type class_name::function(args);

For instance, in our example Node class, we would use this syntax:

class Node 
{
    private: 
    int data;
    int key;
    // ...

    friend int BinaryTree::find(); // Only BinaryTree's find function has access
};

Now the find function of BinaryTree could access the internals of the Nodeclass, but no other function in BinaryTree could. (Though we might want a fewothers to be able to!)

Note that when friends are specified within a class, this does not give theclass itself access to the friend function. That function is not within thescope of the class; it's only an indication that the class will grant accessto the function.

friend and Encapsulation

Some people believe that the idea of having friend classes violates theprinciple of encapsulation because it means that one class can get at theinternals of another. One way to think about this, however, is that friend
issimply part of a class's overall interface that it shows the world. Just likean elevator repairman has access to a different interface than an elevatorrider, some classes or functions require expanded access to the internals ofanother class. Moreover, using
friend allows a class to present a morerestrictive interface to the outside world by hiding more details than may beneeded by anything but the friends of the class.

Finally, friends are particularly common in cases of operator overloadingbecause it is often necessary for an overloaded operator to have access to theinternals of the classes that are arguments to the operator.



A friend function is a function that is not a member of a class but has access to the class's private and protected members. Friend functions are not considered class members; they are normal external
functions that are given special access privileges. Friends are not in the class's scope, and they are not called using the member-selection operators (. and –>) unless they are members of another class. Afriend
function is declared by the class that is granting access. Thefriend declaration can be placed anywhere in the class declaration. It is not affected by the access control keywords.

The following example shows a
Point
class and a friend function, ChangePrivate. The friend function has access to the private data member of thePoint object it receives as a parameter.

// friend_functions.cpp
// compile with: /EHsc
#include <iostream>

using namespace std;
class Point
{
    friend void ChangePrivate( Point & );
public:
    Point( void ) : m_i(0) {}
    void PrintPrivate( void ){cout << m_i << endl; }

private:
    int m_i;
};

void ChangePrivate ( Point &i ) { i.m_i++; }

int main()
{
   Point sPoint;
   sPoint.PrintPrivate();
   ChangePrivate(sPoint);
   sPoint.PrintPrivate();
}

Output

0
1

#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
class Internet;
class Modify_Internet
{
    public:
        Modify_Internet()
        {
            strcpy(cname,"电子科技大学");
        }
        void EditNameAddress(Internet &temp,char *name,char *url);//成员函数的声明
    protected:
        char cname[30];
};
class Internet
{
    public:
        Internet(char *name,char *address)
        {
            strcpy(Internet::name,name);
            strcpy(Internet::address,address);
        }
    friend void ShowNameAddress(Internet &obj);//友元函数的声明
    friend void Modify_Internet::EditNameAddress(Internet &temp,char  *name,char *url);//友元函数的声明
    protected:
        char name[20];
        char address[20];
};
void Modify_Internet::EditNameAddress(Internet &temp,char *name ,char *url)//成员函数的外部定义
{
    strcpy(temp.address,url);
    strcpy(temp.name,name);
    cout<<temp.name<<"|"<<temp.address<<endl;
}
//函数定义,不能写成,void Internet:: ShowNameAddress((Internet &obj)
void  ShowNameAddress(Internet &temp)
{
    cout<<temp.name<<"|"<<temp.address<<endl;
}
int main()
{
    Internet a("王世晖的专栏","blog.csdn.net/shihui512");
    ShowNameAddress(a);
    Modify_Internet b;
    b.EditNameAddress(a,"电子科技大学","www.uestc.edu.cn");
    cout<<"after  Modify_Internet\n";
    ShowNameAddress(a);
}
/*********************************
程序运行结果如下:
王世晖的专栏|blog.csdn.net/shihui512
电子科技大学|www.uestc.edu.cn
after  Modify_Internet
电子科技大学|www.uestc.edu.cn


***********************************/

抱歉!评论已关闭.