⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ei20.htm

📁 一个非常适合初学者入门的有关c++的文档
💻 HTM
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN" "http://www.w3.org/TR/REC-html40/frameset.dtd">
<HTML LANG="EN">
<HEAD>
<title>Effective C++, 2E | Item 20: Avoid data members in the public interface</TITLE>
<LINK REL=STYLESHEET HREF=../INTRO/ECMEC.CSS>

<SCRIPT LANGUAGE="Javascript" SRC="../JAVA/COOKIE.JS"></SCRIPT>
<SCRIPT LANGUAGE="Javascript">var imagemax = 0; setCurrentMax(0);</SCRIPT>
<SCRIPT LANGUAGE="Javascript" SRC="../JAVA/DINGBATS.JS"></SCRIPT>
<SCRIPT LANGUAGE="Javascript">
var dingbase = "EI20_DIR.HTM";
var dingtext = "Item E20, P";
if (self == top) {
 top.location.replace(dingbase + this.location.hash);
}
</SCRIPT>

</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" ONLOAD="setResize()">
<!-- SectionName="E20: Avoid data members in the public interface." -->
<A NAME="5976"></A>
<DIV ALIGN="CENTER"><FONT SIZE="-1">Back to <A HREF="./EI19_FR.HTM" TARGET="_top">Item 19: Differentiate among member functions, non-member functions, and friend functions.</A> &nbsp;&nbsp;<BR>&nbsp;&nbsp;Continue to <A HREF="./EI21_FR.HTM" TARGET="_top">Item 21: Use const whenever possible.</A></FONT></DIV>

<P><A NAME="dingp1"></A><FONT ID="eititle">Item 20: &nbsp;Avoid data members in the public interface.</FONT><SCRIPT>create_link(1);</SCRIPT>
</P>

<A NAME="5977"></A>
<P><A NAME="dingp2"></A>
First, let's look at this issue from the point of view of consistency. If everything in the public interface is a function, clients of your class won't have to scratch their heads trying to remember whether to use parentheses when they want to access a member of your class. They'll just <I>do</I> it, because everything is a function. Over the course of a lifetime, that can save a lot of head <NOBR>scratching.<SCRIPT>create_link(2);</SCRIPT>
</NOBR></P>
<A NAME="5980"></A>
<P><A NAME="dingp3"></A>
You don't buy the consistency argument? How about the fact that using functions gives you much more precise control over the accessibility of data members? If you make a data member public, everybody has read/write access to it, but if you use functions to get and set its value, you can implement no access, read-only access, and read-write access. Heck, you can even implement write-only access if you want <NOBR>to:<SCRIPT>create_link(3);</SCRIPT>
</NOBR></P>
<A NAME="5983"></A>
<UL><PRE>class AccessLevels {
public:
  int getReadOnly() const{ return readOnly; }
</PRE>
</UL><A NAME="5988"></A>
<UL><PRE>  void setReadWrite(int value) { readWrite = value; }
  int getReadWrite() const { return readWrite; }
</PRE>
</UL><A NAME="5989"></A>
<UL><PRE>  void setWriteOnly(int value) { writeOnly = value; }
</PRE>
</UL><A NAME="16337"></A>
<UL><PRE>private:
  int noAccess;                    // no access to this   int
</PRE>
</UL><A NAME="16338"></A>
<UL><PRE>
  int readOnly;                    // read-only access to
                                   // this int
</PRE>
</UL><A NAME="16339"></A>
<UL><PRE>
  int readWrite;                   // read-write access to
                                   // this int
</PRE>
</UL><A NAME="16340"></A>
<UL><PRE>
  int writeOnly;                   // write-only access to
                                   // this int
};
</PRE>
</UL><A NAME="5991"></A>
<P><A NAME="dingp4"></A>
Still not convinced? Then it's time to bring out the big gun: functional abstraction. If you implement access to a data member through a function, you can later replace the data member with a computation, and nobody using your class will be any the <NOBR>wiser.<SCRIPT>create_link(4);</SCRIPT>
</NOBR></P>
<A NAME="5992"></A>
<P><A NAME="dingp5"></A>
<A NAME="p90"></A>For example, suppose you are writing an application in which some automated equipment is monitoring the speed of passing cars. As each car passes, its speed is computed, and the value is added to a collection of all the speed data collected so <NOBR>far:<SCRIPT>create_link(5);</SCRIPT>
</NOBR></P>
<A NAME="5994"></A>
<UL><PRE>class SpeedDataCollection {
public:
  void addValue(int speed);       // add a new data value
</PRE>
</UL><A NAME="5995"></A>
<UL><PRE>  double averageSoFar() const;    // return average speed
};
</PRE>
</UL><A NAME="5996"></A>
<P><A NAME="dingp6"></A>
Now consider the implementation of the member function <CODE>averageSoFar</CODE> (see also <A HREF="../MEC/MI18_FR.HTM#41124" TARGET="_top">Item M18</A>). One way to implement it is to have a data member in the class that is a running average of all the speed data so far collected. Whenever <CODE>averageSoFar</CODE> is called, it just returns the value of that data member. A different approach is to have <CODE>averageSoFar</CODE> compute its value anew each time it's called, something it could do by examining each data value in the collection. (For a more general discussion of these two approaches, see Items <A HREF="../MEC/MI17_FR.HTM#41011" TARGET="_top">M17</A> and <A HREF="../MEC/MI18_FR.HTM#41124" TARGET="_top">M18</A>.)<SCRIPT>create_link(6);</SCRIPT>
</P>
<A NAME="5997"></A>
<P><A NAME="dingp7"></A>
The first approach &#151; keeping a running average &#151; makes each <CODE>SpeedDataCollection</CODE> object bigger, because you have to allocate space for the data member holding the running average. However, <CODE>averageSoFar</CODE> can be implemented very efficiently; it's just an inline function (see <A HREF="./EI33_FR.HTM#6729" TARGET="_top">Item 33</A>) that returns the value of the data member. Conversely, computing the average whenever it's requested will make <CODE>averageSoFar</CODE> run slower, but each <CODE>SpeedDataCollection</CODE> object will be <NOBR>smaller.<SCRIPT>create_link(7);</SCRIPT>
</NOBR></P>
<A NAME="5999"></A>
<P><A NAME="dingp8"></A>
Who's to say which is best? On a machine where memory is tight, and in an application where averages are needed only infrequently, computing the average each time is a better solution. In an application where averages are needed frequently, speed is of the essence, and memory is not an issue, keeping a running average is preferable. The important point is that by accessing the average through a member function, you can use <I>either</I> implementation, a valuable source of flexibility that you wouldn't have if you made a decision to include the running average data member in the public <NOBR>interface.<SCRIPT>create_link(8);</SCRIPT>
</NOBR></P>
<A NAME="6001"></A>
<P><A NAME="dingp9"></A>
The upshot of all this is that you're just asking for trouble by putting data members in the public interface, so play it safe by hiding all your data members behind a wall of functional abstraction. If you do it <I>now</I>, we'll throw in consistency and fine-grained access control at no extra <NOBR>cost!<SCRIPT>create_link(9);</SCRIPT>
</NOBR></P>

<DIV ALIGN="CENTER"><FONT SIZE="-1">Back to <A HREF="./EI19_FR.HTM" TARGET="_top">Item 19: Differentiate among member functions, non-member functions, and friend functions.</A> &nbsp;&nbsp;<BR>&nbsp;&nbsp;Continue to <A HREF="./EI21_FR.HTM" TARGET="_top">Item 21: Use const whenever possible.</A></FONT></DIV>

</BODY>
</HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -