📄 tut4-1.html
字号:
<HTML>
<HEAD>
<TITLE>C++ Tutorial: 4.1, Classes</TITLE>
<META NAME="description" CONTENT="Declaration, initialization and use of classes. Constructors and destructors. Overloading constructors. Pointers to classes. :: scope operator.">
<META NAME="keywords" CONTENT="class empty constructor copy constructor public private protected">
</HEAD>
<BODY BGCOLOR="white">
<!--captut-->
<CENTER>
<TABLE WIDTH=100% CELLPADDING=0 CELLSPACING=1 BORDER=0>
<TR><TD WIDTH=90%>
<FONT SIZE=4> Section 4.1 </FONT><BR>
<FONT SIZE=5><B> 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>
A class is a logical method to organize data and functions in the same structure.
They are declared using keyword <TT><B>class</B></TT>, whose functionality is similar
to that of the C keyword <TT><B>struct</B></TT>, but with the possibility of
including functions as members, instead of only data.
<P>
Its form is:
<BLOCKQUOTE><TT><PRE>
<B>class </B><I>class_name</I> <B>{</B>
<I>permission_label_1</I>:
<I>member1</I><B>;</B>
<I>permission_label_2</I>:
<I>member2</I><B>;
...
}</B> <I>object_name</I><B>;</B>
</PRE></TT></BLOCKQUOTE>
where <TT><B><I>class_name</I></B></TT> is a name for the class (user defined <I>type</I>)
and the optional field <TT><B><I>object_name</I></B></TT> is one, or several, valid object
identifiers. The body of the declaration can contain <TT><B><I>members</I></B></TT>,
that can be either data or function declarations, and
optionally <TT><B><i>permission labels</I></B></TT>,
that can be any of these three keywords:
<TT><B>private:</B></TT>, <TT><B>public:</B></TT> or <TT><B>protected:</B></TT>. They
make reference to the permission which the following <I>members</I> acquire:
<UL>
<LI>
<TT><B>private</B></TT> members of a class are accessible only from other members of their
same class or from their "<I>friend</I>" classes.
<LI>
<TT><B>protected</B></TT> members are accessible from members of their same
class and <I>friend</I> classes, and also from members of their <I>derived</I> classes.
<LI>
Finally, <TT><B>public</B></TT> members are accessible from anywhere the class
is visible.
</UL>
If we declare members of a class before including any permission label, the
members are considered <TT><B>private</B></TT>, since it is the default permission that
the members of a class declared with the <TT><B>class</B></TT> keyword acquire.
<P>
For example:
<BLOCKQUOTE><TT><PRE>
class CRectangle {
int x, y;
public:
void set_values (int,int);
int area (void);
} rect;
</PRE></TT></BLOCKQUOTE>
Declares class <TT><B>CRectangle</B></TT> and an object called <Tt><B>rect</B></TT>
of this class (type). This class contains four members: two variables of type
<TT><B>int</B></TT> (<TT><B>x</B></TT> and <TT><B>y</B></TT>) in the
<TT><B>private</B></TT> section (because private is the default permission)
and two functions in the <TT><B>public</B></TT> section:
<TT><B>set_values()</B></TT> and <TT><B>area()</B></TT>, of which we have only included
the prototype.
<P>
Notice the difference between class name and object name: In the previous example,
<TT><B>CRectangle</B></TT> was the class name (i.e., the user-defined type), whereas
<TT><B>rect</B></TT> was an object of type <TT><B>CRectangle</B></TT>. Is the same
difference that <TT><B>int</B></TT> and <TT><B>a</B></TT> have in the following declaration:
<BLOCKQUOTE><TT>int a;</TT></BLOCKQUOTE>
<TT><B>int</B></TT> is the <I>class name</I> (type) and <TT><B>a</B></TT> is the
<I>object name</I> (variable).
<P>
On successive instructions in the body of the program we can refer to any of the
public members of the object <TT><B>rect</B></TT> as if they were
normal functions or variables, just by putting the <U>object</U>'s name followed by a point
and then the class member (like we did with C <TT><B>struct</B></TT>s). For example:
<blockquote ><TT>
rect.set_value (3,4);<BR>
myarea = rect.area();
</TT></BLOCKQUOTE>
but we will not be able to refer to <TT><B>x</B></TT> or <TT><B>y</B></TT> since they
are <U>private</U> members of the class and they could only be referred from other
members of that same class. Confused? Here is the complete example of class
<TT><B>CRectangle</B></TT>:
<P>
<CENTER>
<TABLE WIDTH=100% CELLPADDING=5 CELLSPACING=5><TR><TD BGCOLOR="#FFFFBF" WIDTH=50% VALIGN="top">
<TT><PRE><I>// classes example</I>
#include <iostream.h>
class CRectangle {
int x, y;
public:
void set_values (int,int);
int area (void) {return (x*y);}
};
void CRectangle::set_values (int a, int b) {
x = a;
y = b;
}
int main () {
CRectangle rect;
rect.set_values (3,4);
cout << "area: " << rect.area();
}
</PRE></TT>
</TD><TD BGCOLOR="silver" WIDTH=50% VALIGN="top"><TT>
<B>area: 12</B>
</TT></TD></TR></TABLE>
</CENTER>
<P>
The new thing in this code is the operator <TT><B>::</B></TT> of scope included in the
definition of <TT><B>set_values()</B></TT>. It is used to declare a member of a class
outside it. Notice that we have defined the behavior of function <TT><B>area()</B></TT>
within the definition of the <TT><B>CRectangle</B></TT> class - given its extreme simplicity.
Whereas <TT><B>set_values()</B></TT> has only its protype declared within the class
but its definition is outside. In this outside declaration we must use the operator of
scope <TT><B>::</B></TT>.
<P>
The scope operator (<TT><B>::</B></TT>) specifies the class to which the member
being declared belongs, granting exactly the same scope properties
as if it was directly defined within the class. For example, in the function
<TT><B>set_values()</B></TT> of the previous code, we have referred to the variables
<TT><B>x</B></TT> and <TT><B>y</B></TT>, that are members of class
<TT><B>CRectangle</B></TT> and that are only visible inside it and its members
(since they are <TT><B>private</B></TT>).
<P>
The only difference between defining a class member function completely within its
class and to include only the prototype, is that in the first case the function
will automatically be considered <I>inline</I> by the compiler, while in the second
it will be a normal (not-inline) class member function.
<P>
The reason why we have made <TT><B>x</B></TT> and <TT><B>y</B></TT>
<TT><B>private</B></TT> members (remember that if nothing else is said all members of a
class defined with keyword <I>class</I> have <TT><B>private</B></TT> access) it is because
we have already defined a function to introduce those values in the object
(<TT><B>set_values()</B></TT>) and therefore the rest of the program does not have
a way to directly access them. Perhaps in a so simple example as this you
do not see a great utility protecting those two variables, but in greater projects
it may be very important that values cannot be modified in an unexpected way
(unexpected from the point of view of the object).
<P>
One of the greater advantages of a class is that we can declare several different
objects from it. For example, following with the previous example of class
<TT><B>CRectangle</B></TT>, we could have declared the object <TT><B>rectb</B></TT>
in addition to the object <TT><B>rect</B></TT> :
<P>
<CENTER>
<TABLE WIDTH=100% CELLPADDING=5 CELLSPACING=5><TR><TD BGCOLOR="#FFFFBF" WIDTH=50% VALIGN="top">
<TT><PRE><I>// class example</I>
#include <iostream.h>
class CRectangle {
int x, y;
public:
void set_values (int,int);
int area (void) {return (x*y);}
};
void CRectangle::set_values (int a, int b) {
x = a;
y = b;
}
int main () {
CRectangle rect, rectb;
rect.set_values (3,4);
rectb.set_values (5,6);
cout << "rect area: " << rect.area() << endl;
cout << "rectb area: " << rectb.area() << endl;
}
</PRE></TT>
</TD><TD BGCOLOR="silver" WIDTH=50% VALIGN="top"><TT>
<B>rect area: 12<BR>rectb area: 30</B>
</TT></TD></TR></TABLE>
</CENTER>
<P>
Notice that the call to <TT><B>rect.area()</B></TT> does not give the same
result as the call to <TT><B>rectb.area()</B></TT>. This is because each object
of class <TT><B>CRectangle</B></TT> has its own variables <TT><B>x</B></TT>
and <TT><B>y</B></TT>, and its own functions <TT><B>set_value()</B></TT>
and <TT><B>area()</B></TT>.
<P>
On that is based the concept of <I><B>object</B></I> and
<I><B>object-oriented programming</B></I>. In that data and functions are properties
of the object, instead of the usual view of objects as function parameters in structured
programming. In this and the following sections we will discuss advantages of this
methodology.
<P>
In this concrete case, the class (type of object) to which we were talking about is
<TT><B>CRectangle</B></TT>, of which there are two instances, or objects:
<TT><B>rect</B></TT> and <TT><B>rectb</B></TT>, each one with its own member variables
and member functions.
<P>
<H2>Constructors and destructors</H2>
Objects generally need to initialize variables or assign dynamic memory during their
process of creation to become totally operative and to avoid returning unexpected values
during their execution. For example, what would happen if in the previous example we
called the function <TT><B>area()</B></TT> before having called function
<TT><B>set_values</B></TT>? Probably an indetermined result since the members
<TT><B>x</B></TT> and <TT><B>y</B></TT> would have never been assigned a value.
<P>
In order to avoid that, a class can include a special function: a <I>constructor</I>,
which can be declared by naming a member function with the <U>same name</U> as the class.
This constructor <I>function</I> will be called automatically when a new instance of
the class is created (when declaring a new object or allocating an object of that class) and
only then. We are going to implement <TT><B>CRectangle</B></TT> including a
<I>constructor</I>:
<P>
<CENTER>
<TABLE WIDTH=100% CELLPADDING=5 CELLSPACING=5><TR><TD BGCOLOR="#FFFFBF" WIDTH=50% VALIGN="top">
<TT><PRE><I>// classes example</I>
#include <iostream.h>
class CRectangle {
int width, height;
public:
CRectangle (int,int);
int area (void) {return (width*height);}
};
CRectangle::CRectangle (int a, int b) {
width = a;
height = b;
}
int main () {
CRectangle rect (3,4);
CRectangle rectb (5,6);
cout << "rect area: " << rect.area() << endl;
cout << "rectb area: " << rectb.area() << endl;
}
</PRE></TT>
</TD><TD BGCOLOR="silver" WIDTH=50% VALIGN="top"><TT>
<B>rect area: 12<BR>rectb area: 30</B>
</TT></TD></TR></TABLE>
</CENTER>
<P>
As you can see, the result of this example is identical to the previous one.
In this case we have only replaced the function <TT><B>set_values</B></TT>, that no longer
exists, by a class <I>constructor</I>. Notice the way in which the parameters
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -