📄 tut4-3.html
字号:
<HTML>
<HEAD>
<TITLE>C++ Tutorial: 4.3, Relationships between Classes</TITLE>
<META NAME="description" CONTENT="friend functions and classes. Inheritance between classes. Constructors and destructors with inheritance. Multiple inheritance.">
<META NAME="keywords" CONTENT="public protected private friend :">
</HEAD>
<BODY BGCOLOR="white">
<!--captut-->
<CENTER>
<TABLE WIDTH=100% CELLPADDING=0 CELLSPACING=1 BORDER=0>
<TR><TD WIDTH=90%>
<FONT SIZE=4> Section 4.3 </FONT><BR>
<FONT SIZE=5><B>Relationships between classes</B></FONT>
</TD><TD><!--ad--><!--#include virtual="/ad/ad468.shtml"--><!--/ad-->
</TD><TD VALIGN="bottom"><A HREF="http://www.cplusplus.com/doc/tutorial/">
<IMG SRC="head.gif" ALT="cplusplus.com" BORDER=0></A></TD></TR>
<TR><TD BGCOLOR="#0000FF" ALIGN="center" COLSPAN=3>
<IMG SRC="head0.gif" WIDTH=2 HEIGHT=2 BORDER=0></TD></TR>
</TABLE>
</CENTER>
<!--/captut-->
<P>
<H2>Friend functions (<TT>friend</TT> keyword)</H2>
In the previous section we have seen that there were three levels of internal protection
for the different members of a class: <B>public</B>, <B>protected</B> and <B>private</B>.
In the case of members
<I>protected</I> and <I>private</I>, these could not be accessed from outside the same
class at which they are declared. Nevertheless, this rule can be transgressed with the
use of the <TT><I>friend</I></TT> keyword in a class, so we can allow
an external function to gain access to the <TT><B>protected</B></TT> and
<TT><B>private</B></TT> members of a class.
<P>
In order to allow an external function to have access to the <TT><B>private</B></TT>
and <TT><B>protected</B></TT> members of a class we have to declare
the prototye of the external function that will gain access preceded by
the keyword <TT><B>friend</B></TT> within the class declaration that shares its members.
In the following example we declare the friend function <TT><B>duplicate</B></TT>:
<P>
<CENTER>
<TABLE WIDTH=100% CELLPADDING=5 CELLSPACING=5><TR><TD BGCOLOR="#FFFFBF" WIDTH=50% VALIGN="top">
<TT><PRE><I>// friend functions</I>
#include <iostream.h>
class CRectangle {
int width, height;
public:
void set_values (int, int);
int area (void) {return (width * height);}
friend CRectangle duplicate (CRectangle);
};
void CRectangle::set_values (int a, int b) {
width = a;
height = b;
}
CRectangle duplicate (CRectangle rectparam)
{
CRectangle rectres;
rectres.width = rectparam.width*2;
rectres.height = rectparam.height*2;
return (rectres);
}
int main () {
CRectangle rect, rectb;
rect.set_values (2,3);
rectb = duplicate (rect);
cout << rectb.area();
}
</PRE></TT>
</TD><TD BGCOLOR="silver" WIDTH=50% VALIGN="top"><TT>
<B>24</B>
</TT></TD></TR></TABLE>
</CENTER>
<P>
From within the <TT><B>duplicate</B></TT> function, that is a friend of
<TT><B>CRectangle</B></TT>, we have been able to access
the members <TT><B>width</B></TT> and <TT><B>height</B></TT> of different objects
of type <TT><B>CRectangle</B></TT>. Notice that neither in the declaration of
<TT><B>duplicate()</B></TT> nor in its later use in <TT><B>main()</B></TT>
have we considered <TT><B>duplicate</B></TT> as a member of class
<TT><B>CRectangle</B></TT>. It isn't.
<P>
The friend functions can serve, for example, to conduct operations between two different
classes. Generally the use of friend functions is out of an object-oriented programming
methodology, so whenever possible it is better to use members of the same class to make
the process. Such as in the previous example, it would have been shorter to integrate
<TT><B>duplicate()</B></TT> within the class <TT><B>CRectangle</B></TT>.
<P>
<H2>Friend classes (<TT>friend</TT>)</H2>
Just as we have the possibility to define a friend function, we can also define a class
as friend of another one, allowing that the second one access to the
<TT><B>protected</B></TT> and <TT><B>private</B></TT> members of the first one.
<P>
<CENTER>
<TABLE WIDTH=100% CELLPADDING=5 CELLSPACING=5><TR><TD BGCOLOR="#FFFFBF" WIDTH=50% VALIGN="top">
<TT><PRE><I>// friend class</I>
#include <iostream.h>
class CSquare;
class CRectangle {
int width, height;
public:
int area (void)
{return (width * height);}
void convert (CSquare a);
};
class CSquare {
private:
int side;
public:
void set_side (int a)
{side=a;}
friend class CRectangle;
};
void CRectangle::convert (CSquare a) {
width = a.side;
height = a.side;
}
int main () {
CSquare sqr;
CRectangle rect;
sqr.set_side(4);
rect.convert(sqr);
cout << rect.area();
return 0;
}
</PRE></TT>
</TD><TD BGCOLOR="silver" WIDTH=50% VALIGN="top"><TT>
<B>16</B>
</TT></TD></TR></TABLE>
</CENTER>
<P>
In this example we have declared <TT><B>CRectangle</B></TT> as a friend of
<TT><B>CSquare</B></TT> so that <TT><B>CRectangle</B></TT> can access the
<TT><B>protected</B></TT> and <TT><B>private</B></TT> members of <TT><B>CSquare</B></TT>,
more concretely <TT><B>CSquare::side</B></TT>, that defines the square side width.
<P>
You may also see something new in the first instruction of the program, that is the empty
prototype of class <TT><B>CSquare</B></TT>. This is necessary because within the declaration
of <TT><B>CRectangle</B></TT> we refer to <TT><B>CSquare</B></TT> (as a parameter
in <TT><B>convert()</B></TT>). The definition of <TT><B>CSquare</B></TT> is included
later, so if we did not include a previous definition for <TT><B>CSquare</B></TT>
this class would not be visible from within the definition of <TT><B>CRectangle</B></TT>.
<P>
Consider that friendships are not corresponded if we do not explicitly specify it.
In our <TT><B>CSquare</B></TT> example <TT><B>CRectangle</B></TT> is considered as a
class friend, but <TT><B>CRectangle</B></TT> does not do the proper thing with
<TT><B>CSquare</B></TT>, so <TT><B>CRectangle</B></TT> can access to the
<TT><B>protected</B></TT> and <TT><B>private</B></TT> members of <TT><B>CSquare</B></TT>
but not the reverse way. Although nothing prevents us from declaring
<TT><B>CSquare</B></TT> as a friend of <TT><B>CRectangle</B></TT>.
<P>
<H2>Inheritance between classes</H2>
An important feature of classes is inheritance. This allows us to create an object
derived from another one, so that it may include some of the other's members plus its own.
For example, we are going to suppose that we want to declare a series of classes
that describe polygons like our <TT><B>CRectangle</B></TT>, or
<TT><B>CTriangle</B></TT>. They have certain common features, such as
both can be described by means of only two sides: height and base.
<P>
This could be represented in the world of classes with a class <TT><B>CPolygon</B></TT>
from which we would derive the two referred ones,
<TT><B>CRectangle</B></TT> and <TT><B>CTriangle</B></TT>.
<blockquote ><IMG SRC="imgclas1.gif"></BLOCKQUOTE>
The class <TT><B>CPolygon</B></TT> would contain members that are common for all
polygons. In our case: <TT><B>width</B></TT> and <TT><B>height</B></TT>. And
<TT><B>CRectangle</B></TT> and <TT><B>CTriangle</B></TT>
would be its derived classes.
<P>
Classes derived from others inherit all the visible members of the base class.
That means that if a base class includes a member <TT><B>A</B></TT> and we derive it
to another class with another member called <TT><B>B</B></TT>, the derived class will
contain both <TT><B>A</B></TT> and <TT><B>B</B></TT>.
<P>
In order to derive a class from another, we must use the operator <TT><B>:</B></TT>
(colon) in the declaration of the derived class in the following way:
<blockquote ><TT>
<B>class </B><I>derived_class_name</I><B>: public</B> <I>base_class_name</I><B>;</B>
</TT></BLOCKQUOTE>
where <TT><I>derived_class_name</I></TT> is the name of the <I>derived</I> class and
<TT><I>base_class_name</I></TT> is the name of the class on which it is based.
<TT><B>public</B></TT> may be replaced by any of the other access specifiers
<TT><B>protected</B></TT> or <TT><B>private</B></TT>, and describes the access
for the inherited members, as we will see right after this example:
<P>
<CENTER>
<TABLE WIDTH=100% CELLPADDING=5 CELLSPACING=5><TR><TD BGCOLOR="#FFFFBF" WIDTH=50% VALIGN="top">
<TT><PRE><I>// derived classes</I>
#include <iostream.h>
class CPolygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b;}
};
class CRectangle: public CPolygon {
public:
int area (void)
{ return (width * height); }
};
class CTriangle: public CPolygon {
public:
int area (void)
{ return (width * height / 2); }
};
int main () {
CRectangle rect;
CTriangle trgl;
rect.set_values (4,5);
trgl.set_values (4,5);
cout << rect.area() << endl;
cout << trgl.area() << endl;
return 0;
}
</PRE></TT>
</TD><TD BGCOLOR="silver" WIDTH=50% VALIGN="top"><TT>
<B>20<BR>10</B>
</TT></TD></TR></TABLE>
</CENTER>
<P>
As you may see, objects of classes <TT><B>CRectangle</B></TT> and <TT><B>CTriangle</B></TT>
each contain members of <TT><B>CPolygon</B></TT>, that are:
<TT><B>width</TT></B>, <TT><B>height</B></TT> and <TT><B>set_values()</B></TT>.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -