📄 chapter09.html
字号:
<font color=#0000ff>class</font> Rectangle {
<font color=#0000ff>int</font> width, height;
<font color=#0000ff>public</font>:
Rectangle(<font color=#0000ff>int</font> w = 0, <font color=#0000ff>int</font> h = 0)
: width(w), height(h) {}
<font color=#0000ff>int</font> getWidth() <font color=#0000ff>const</font> { <font color=#0000ff>return</font> width; }
<font color=#0000ff>void</font> setWidth(<font color=#0000ff>int</font> w) { width = w; }
<font color=#0000ff>int</font> getHeight() <font color=#0000ff>const</font> { <font color=#0000ff>return</font> height; }
<font color=#0000ff>void</font> setHeight(<font color=#0000ff>int</font> h) { height = h; }
};
<font color=#0000ff>int</font> main() {
Rectangle r(19, 47);
<font color=#009900>// Change width & height:</font>
r.setHeight(2 * r.getWidth());
r.setWidth(2 * r.getHeight());
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Of course, accessors and mutators
don’t have to be simple pipelines to an internal variable. Sometimes they
can perform more sophisticated calculations. The following example uses the
Standard C library time functions to produce a simple <B>Time</B>
class:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C09:Cpptime.h</font>
<font color=#009900>// A simple time class</font>
#ifndef CPPTIME_H
#define CPPTIME_H
#include <ctime>
#include <cstring>
<font color=#0000ff>class</font> Time {
std::time_t t;
std::tm local;
<font color=#0000ff>char</font> asciiRep[26];
<font color=#0000ff>unsigned</font> <font color=#0000ff>char</font> lflag, aflag;
<font color=#0000ff>void</font> updateLocal() {
<font color=#0000ff>if</font>(!lflag) {
local = *std::localtime(&t);
lflag++;
}
}
<font color=#0000ff>void</font> updateAscii() {
<font color=#0000ff>if</font>(!aflag) {
updateLocal();
std::strcpy(asciiRep,std::asctime(&local));
aflag++;
}
}
<font color=#0000ff>public</font>:
Time() { mark(); }
<font color=#0000ff>void</font> mark() {
lflag = aflag = 0;
std::time(&t);
}
<font color=#0000ff>const</font> <font color=#0000ff>char</font>* ascii() {
updateAscii();
<font color=#0000ff>return</font> asciiRep;
}
<font color=#009900>// Difference in seconds:</font>
<font color=#0000ff>int</font> delta(Time* dt) <font color=#0000ff>const</font> {
<font color=#0000ff>return</font> <font color=#0000ff>int</font>(std::difftime(t, dt->t));
}
<font color=#0000ff>int</font> daylightSavings() {
updateLocal();
<font color=#0000ff>return</font> local.tm_isdst;
}
<font color=#0000ff>int</font> dayOfYear() { <font color=#009900>// Since January 1</font>
updateLocal();
<font color=#0000ff>return</font> local.tm_yday;
}
<font color=#0000ff>int</font> dayOfWeek() { <font color=#009900>// Since Sunday</font>
updateLocal();
<font color=#0000ff>return</font> local.tm_wday;
}
<font color=#0000ff>int</font> since1900() { <font color=#009900>// Years since 1900</font>
updateLocal();
<font color=#0000ff>return</font> local.tm_year;
}
<font color=#0000ff>int</font> month() { <font color=#009900>// Since January</font>
updateLocal();
<font color=#0000ff>return</font> local.tm_mon;
}
<font color=#0000ff>int</font> dayOfMonth() {
updateLocal();
<font color=#0000ff>return</font> local.tm_mday;
}
<font color=#0000ff>int</font> hour() { <font color=#009900>// Since midnight, 24-hour clock</font>
updateLocal();
<font color=#0000ff>return</font> local.tm_hour;
}
<font color=#0000ff>int</font> minute() {
updateLocal();
<font color=#0000ff>return</font> local.tm_min;
}
<font color=#0000ff>int</font> second() {
updateLocal();
<font color=#0000ff>return</font> local.tm_sec;
}
};
#endif <font color=#009900>// CPPTIME_H ///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The Standard C library
<A NAME="Index1642"></A>functions have multiple representations for time, and
these are all part of the <B>Time</B> class. However, it isn’t necessary
to update all of them, so instead the <A NAME="Index1643"></A><B>time_t t</B> is
used as the base representation, and the <B>tm local</B> and ASCII character
representation <B>asciiRep</B> each have flags to indicate if they’ve been
updated to the current <B>time_t</B>. The two <B>private</B> functions
<B>updateLocal( )</B> and <B>updateAscii( )</B> check the flags and
conditionally perform the update.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The constructor calls the
<B>mark( )</B> function (which the user can also call to force the object
to represent the current time), and this clears the two flags to indicate that
the local time and ASCII representation are now invalid. The
<B>ascii( )</B> function calls <B>updateAscii( )</B>, which copies the
result of the Standard C library function
<A NAME="Index1644"></A><B>asctime( )</B> into a local buffer because
<B>asctime( )</B> uses a static data area that is overwritten if the
function is called elsewhere. The <B>ascii( )</B> function return value is
the address of this local buffer.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">All the functions starting with
<B>daylightSavings( )</B> use the <B>updateLocal( )</B> function,
which causes the resulting composite inlines to be fairly large. This
doesn’t seem worthwhile, especially considering you probably won’t
call the functions very much. However, this doesn’t mean all the functions
should be made non-inline. If you make other functions non-inline, at least keep
<B>updateLocal( )</B> inline so that its code will be duplicated in the
non-inline functions, eliminating extra function-call overhead.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Here’s a small test
program:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C09:Cpptime.cpp</font>
<font color=#009900>// Testing a simple time class</font>
#include <font color=#004488>"Cpptime.h"</font>
#include <iostream>
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;
<font color=#0000ff>int</font> main() {
Time start;
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 1; i < 1000; i++) {
cout << i << ' ';
<font color=#0000ff>if</font>(i%10 == 0) cout << endl;
}
Time end;
cout << endl;
cout << <font color=#004488>"start = "</font> << start.ascii();
cout << <font color=#004488>"end = "</font> << end.ascii();
cout << <font color=#004488>"delta = "</font> << end.delta(&start);
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">A <B>Time</B> object is created, then
some time-consuming activity is performed, then a second <B>Time</B> object is
created to mark the ending time. These are used to show starting, ending, and
elapsed
times.</FONT><A NAME="_Toc305593213"></A><A NAME="_Toc305628685"></A><A NAME="_Toc312373930"></A><A NAME="_Toc472654903"></A><BR></P></DIV>
<A NAME="Heading284"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Stash & Stack with inlines</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Armed with inlines, we can now convert
the <A NAME="Index1645"></A><B>Stash</B> and <B>Stack</B> classes to be more
efficient:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C09:Stash4.h</font>
<font color=#009900>// Inline functions</font>
#ifndef STASH4_H
#define STASH4_H
#include <font color=#004488>"../require.h"</font>
<font color=#0000ff>class</font> Stash {
<font color=#0000ff>int</font> size; <font color=#009900>// Size of each space</font>
<font color=#0000ff>int</font> quantity; <font color=#009900>// Number of storage spaces</font>
<font color=#0000ff>int</font> next; <font color=#009900>// Next empty space</font>
<font color=#009900>// Dynamically allocated array of bytes:</font>
<font color=#0000ff>unsigned</font> <font color=#0000ff>char</font>* storage;
<font color=#0000ff>void</font> inflate(<font color=#0000ff>int</font> increase);
<font color=#0000ff>public</font>:
Stash(<font color=#0000ff>int</font> sz) : size(sz), quantity(0),
next(0), storage(0) {}
Stash(<font color=#0000ff>int</font> sz, <font color=#0000ff>int</font> initQuantity) : size(sz),
quantity(0), next(0), storage(0) {
inflate(initQuantity);
}
Stash::~Stash() {
<font color=#0000ff>if</font>(storage != 0)
<font color=#0000ff>delete</font> []storage;
}
<font color=#0000ff>int</font> add(<font color=#0000ff>void</font>* element);
<font color=#0000ff>void</font>* fetch(<font color=#0000ff>int</font> index) <font color=#0000ff>const</font> {
require(0 <= index, <font color=#004488>"Stash::fetch (-)index"</font>);
<font color=#0000ff>if</font>(index >= next)
<font color=#0000ff>return</font> 0; <font color=#009900>// To indicate the end</font>
<font color=#009900>// Produce pointer to desired element:</font>
<font color=#0000ff>return</font> &(storage[index * size]);
}
<font color=#0000ff>int</font> count() <font color=#0000ff>const</font> { <font color=#0000ff>return</font> next; }
};
#endif <font color=#009900>// STASH4_H ///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The small functions obviously work well
as inlines, but notice that the two largest functions are still left as
non-inlines, since inlining them probably wouldn’t cause any performance
gains:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C09:Stash4.cpp {O}</font>
#include <font color=#004488>"Stash4.h"</font>
#include <iostream>
#include <cassert>
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;
<font color=#0000ff>const</font> <font color=#0000ff>int</font> increment = 100;
<font color=#0000ff>int</font> Stash::add(<font color=#0000ff>void</font>* element) {
<font color=#0000ff>if</font>(next >= quantity) <font color=#009900>// Enough space left?</font>
inflate(increment);
<font color=#009900>// Copy element into storage,</font>
<font color=#009900>// starting at next empty space:</font>
<font color=#0000ff>int</font> startBytes = next * size;
<font color=#0000ff>unsigned</font> <font color=#0000ff>char</font>* e = (<font color=#0000ff>unsigned</font> <font color=#0000ff>char</font>*)element;
<font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i < size; i++)
storage[startBytes + i] = e[i];
next++;
<font color=#0000ff>return</font>(next - 1); <font color=#009900>// Index number</font>
}
<font color=#0000ff>void</font> Stash::inflate(<font color=#0000ff>int</font> increase) {
assert(increase >= 0);
<font color=#0000ff>if</font>(increase == 0) <font color=#0000ff>return</font>;
<font color=#0000ff>int</font> newQuantity = quantity + increase;
<font color=#0000ff>int</font> newBytes = newQuantity * size;
<font color=#0000ff>int</font> oldBytes = quantity * size;
<font color=#0000ff>unsigned</font> <font color=#0000ff>char</font>* b = <font color=#0000ff>new</font> <font color=#0000ff>unsigned</font> <font color=#0000ff>char</font>[newBytes];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -