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

📄 e.htm

📁 一个非常适合初学者入门的有关c++的文档
💻 HTM
📖 第 1 页 / 共 5 页
字号:

</NOBR></P>

<UL><A NAME="1739"></A>
<PRE>class A {
public:
  A();                                   // default constructor
};
</PRE><A NAME="12898"></A>
<PRE>A arrayA[10];                            // 10 constructors called

class B {
public:
  B(int x = 0);                          // default constructor
};
<A NAME="12901"></A>
B arrayB[10];                            // 10 constructors called,
                                         // each with an arg of 0
</PRE><A NAME="12905"></A>
<PRE><A NAME="p6"></A>class C {
public:
  C(int x);                              // not a&#32;default constructor
};
</PRE><A NAME="12902"></A>
<PRE>C arrayC[10];                            // error!
</PRE>
</UL>

<P><A NAME="dingp56"></A><A NAME="1742"></A>
You may find that your compilers reject arrays of objects when a class's default constructor has default parameter values. For example, some compilers refuse to accept the definition of <CODE>arrayB</CODE> above, even though it receives the blessing of the C++ standard. This is an example of the kind of discrepancy that can exist between the standard's description of C++ and a particular compiler's implementation of the language. Every compiler I know of has a few of these shortcomings. Until compiler vendors catch up to the standard, be prepared to be flexible, and take solace in the certainty that someday in the not-too-distant future, the C++ described in the standard will be the same as the language accepted by C++ <NOBR>compilers.<SCRIPT>create_link(56);</SCRIPT>

</NOBR></P>

<P><A NAME="dingp57"></A><A NAME="1743"></A>
Incidentally, if you want to create an array of objects for which there is no default constructor, the usual ploy is to define an array of <I>pointers</I> instead. Then you can initialize each pointer separately by using <CODE>new</CODE>:<SCRIPT>create_link(57);</SCRIPT>

</P>

<UL><A NAME="1744"></A>
<PRE>C *ptrArray[10];                          // no constructors called
<A NAME="1745"></A>
ptrArray[0] = new C(22);                  // allocate and construct
                                          // 1 C object
</PRE><A NAME="1746"></A>
<PRE>ptrArray[1] = new C(4);                   // ditto
</PRE><A NAME="1747"></A>
<PRE>...
</PRE>
</UL>

<P><A NAME="dingp58"></A><A NAME="1748"></A>
This suffices almost all the time. When it doesn't, you'll probably have to fall back on the more advanced (and hence more obscure) "placement <CODE>new</CODE>" approach described in <A HREF="../MEC/M_FR.HTM#5218" TARGET="_top" onMouseOver = "self.status = 'Item M4'; return true" onMouseOut = "self.status = self.defaultStatus">Item M4</A>.<SCRIPT>create_link(58);</SCRIPT>

</P>

<P><A NAME="dingp59"></A><A NAME="20725"></A>
Back on the terminology front, a <I>copy constructor</I> is used to initialize an object with a different object of the same <NOBR>type:<SCRIPT>create_link(59);</SCRIPT>

</NOBR></P>

<UL><A NAME="20804"></A>
<PRE>class String {
public:
  String();                               // default constructor
  String(const String&amp; rhs);              // copy constructor
  ...
</PRE><A NAME="12329"></A>
<PRE>private:
  char *data;
};
</PRE><A NAME="1751"></A>
<PRE>String s1;                                 // call default constructor
String s2(s1);                             // call copy constructor
String s3 = s2;                            // call copy constructor
</PRE>
</UL>

<P><A NAME="dingp60"></A><A NAME="1752"></A>
Probably the most important use of the copy constructor is to define what it means to pass and return objects by value. As an example, consider the following (inefficient) way of writing a function to concatenate two <CODE>String</CODE> <NOBR>objects:<SCRIPT>create_link(60);</SCRIPT>

</NOBR></P>

<UL><A NAME="1753"></A>
<PRE><A NAME="p7"></A>const String operator+(String s1, String s2)
{
  String temp;
</PRE><A NAME="3365"></A>
<PRE>  delete [] temp.data;
</PRE><A NAME="12334"></A>
<PRE>  temp.data =
    new char[strlen(s1.data) + strlen(s2.data) + 1];
</PRE><A NAME="12335"></A>
<PRE>  strcpy(temp.data, s1.data);
  strcat(temp.data, s2.data);
</PRE><A NAME="1755"></A>
<PRE>  return temp;
}
</PRE><A NAME="1756"></A>
<PRE>String a("Hello");
String b(" world");
String c = a + b;                          // c = String("Hello world")
</PRE>
</UL>

<P><A NAME="dingp61"></A><A NAME="1757"></A>
This <CODE>operator+</CODE> takes two <CODE>String</CODE> objects as parameters and returns one <CODE>String</CODE> object as a result. Both the parameters and the result will be passed by value, so there will be one copy constructor called to initialize <CODE>s1</CODE> with <CODE>a</CODE>, one to initialize <CODE>s2</CODE> with <CODE>b</CODE>, and one to initialize <CODE>c</CODE> with <CODE>temp</CODE>. In fact, there might even be some additional calls to the copy constructor if a compiler decides to generate intermediate temporary objects, which it is allowed to do (see <A HREF="../MEC/M_FR.HTM#41177" TARGET="_top" onMouseOver = "self.status = 'Item M19'; return true" onMouseOut = "self.status = self.defaultStatus">Item M19</A>). The important point here is that pass-by-value <I>means</I> "call the copy <NOBR>constructor."<SCRIPT>create_link(61);</SCRIPT>

</NOBR></P>

<P><A NAME="dingp62"></A><A NAME="1758"></A>
By the way, you wouldn't really implement <CODE>operator+</CODE> for <CODE>String</CODE>s like this. Returning a <CODE>const</CODE> <CODE>String</CODE> object is correct (see Items <A HREF="#6003"onMouseOver = "self.status = '21'; return true" onMouseOut = "self.status = self.defaultStatus">21</A> and <A HREF="#6210"onMouseOver = "self.status = '23'; return true" onMouseOut = "self.status = self.defaultStatus">23</A>), but you would want to pass the two parameters by reference (see <A HREF="#6133"onMouseOver = "self.status = 'Item 22'; return true" onMouseOut = "self.status = self.defaultStatus">Item 22</A>).<SCRIPT>create_link(62);</SCRIPT>

</P>

<P><A NAME="dingp63"></A><A NAME="12986"></A>
Actually, you wouldn't write <CODE>operator+</CODE> for <CODE>String</CODE>s at all if you could help it, and you should be able to help it almost all the time. That's because the standard C++ library (see <A HREF="#8392"onMouseOver = "self.status = 'Item 49'; return true" onMouseOut = "self.status = self.defaultStatus">Item 49</A>) contains a string type (cunningly named <CODE>string</CODE>), as well as an <CODE>operator+</CODE> for <CODE>string</CODE> objects that does almost exactly what the <CODE>operator+</CODE> above does. In this book, I use both <CODE>String</CODE> and <CODE>string</CODE> objects, but I use them in different ways. (Note that the former name is capitalized, the latter name is not.) If I need just a generic string and I don't care how it's implemented, I use the <CODE>string</CODE> type that is part of the standard C++ library. That's what you should do, too. Often, however, I want to make a point about how C++ behaves, and in those cases, I need to show some implementation code. That's when I use the (nonstandard) <CODE>String</CODE> class. As a programmer, you should use the standard <CODE>string</CODE> type whenever you need a string object; the days of developing your own string class as a C++ rite of passage are behind us. However, you still need to understand the issues that go into the development of classes like <A NAME="p8"></A><CODE>string</CODE>. <CODE>String</CODE> is convenient for that purpose (and for that purpose only). As for raw <CODE>char*</CODE>-based strings, you shouldn't use those antique throw-backs unless you have a <i>very</i> good reason. Well-implemented <CODE>string</CODE> types can now be superior to <CODE>char*</CODE>s in virtually every way &#151; including efficiency (see <A HREF="#8392"onMouseOver = "self.status = 'Item 49'; return true" onMouseOut = "self.status = self.defaultStatus">Item 49</A> and Items <A HREF="../MEC/M_FR.HTM#6073" TARGET="_top" onMouseOver = "self.status = 'M29'; return true" onMouseOut = "self.status = self.defaultStatus">M29</A>-<A HREF="../MEC/M_FR.HTM#6074" TARGET="_top" onMouseOver = "self.status = 'M30'; return true" onMouseOut = "self.status = self.defaultStatus">M30</A>).<SCRIPT>create_link(63);</SCRIPT>

</P>

<P><A NAME="dingp64"></A><A NAME="1759"></A>

⌨️ 快捷键说明

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