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

📄 mi34.htm

📁 一个非常适合初学者入门的有关c++的文档
💻 HTM
📖 第 1 页 / 共 2 页
字号:
  void drawLine(int x1, int y1, int x2, int y2);
  void twiddleBits(unsigned char bits);
  void simulate(int iterations);
  ...
<A NAME="36847"></A>
#ifdef __cplusplus
<A NAME="36840"></A>
}
<A NAME="36851"></A>
#endif
</PRE>
</UL>
<A NAME="36806"></A>
<P><A NAME="dingp18"></A>
There is, by the way, no such thing as a "standard" name mangling algorithm. Different compilers are free to mangle names in different ways, and different compilers do. This is a good thing. If all compilers mangled names the same way, you might be lulled into thinking they all generated compatible code. The way things are now, if you try to mix object code from incompatible C++ compilers, there's a good chance you'll get an error during linking, because the mangled names won't match up. This implies you'll probably have other compatibility problems, too, and it's better to find out about such incompatibilities sooner than <NOBR>later,<SCRIPT>create_link(18);</SCRIPT>
</NOBR></P>

<P><A NAME="dingp19"></A><font ID="mhtitle">Initialization of Statics</font><SCRIPT>create_link(19);</SCRIPT>
</P>

<A NAME="86059"></A>
<P><A NAME="dingp20"></A>
Once you've mastered name mangling, you need to deal with the fact that in C++, lots of code can get executed before and after <CODE>main</CODE>. In particular, the constructors of static class objects and objects at global, namespace, and file scope are usually called before the body of <CODE>main</CODE> is executed. This process is known as <I>static initialization</I> (see <a href="../EC/EI47_FR.HTM#8299" TARGET="_top">Item E47</A>). This is in direct opposition to the way we normally think about C++ and C programs, in which we view <CODE>main</CODE> as the entry point to execution of the program. Similarly, objects that are created through static initialization must have their destructors called during <I>static destruction</I>; that process typically takes place after <CODE>main</CODE> has finished <NOBR>executing.<SCRIPT>create_link(20);</SCRIPT>
</NOBR></P><A NAME="36899"></A>
<P><A NAME="dingp21"></A>
To resolve the dilemma that <CODE>main</CODE> is supposed to be invoked first, yet objects need to be constructed before <CODE>main</CODE> is executed, many compilers insert a call to a special compiler-written function at the beginning <A NAME="p274"></A>of <CODE>main</CODE>, and it is this special function that takes care of static initialization. Similarly, compilers often insert a call to another special function at the end of <CODE>main</CODE> to take care of the destruction of static objects. Code generated for <CODE>main</CODE> often looks as if <CODE>main</CODE> had been written like <NOBR>this:<SCRIPT>create_link(21);</SCRIPT>
</NOBR></P>
<A NAME="36903"></A>
<UL><PRE>
int main(int argc, char *argv[])
{
  performStaticInitialization();         // generated by the
                                         // implementation
<A NAME="36913"></A>
<I>  the statements you put in main go here;</I>
<A NAME="36914"></A>
  performStaticDestruction();            // generated by the
                                         // implementation
}</PRE>
</UL><A NAME="36921"></A>
<P><A NAME="dingp22"></A>
Now don't take this too literally. The functions <CODE>performStaticInitialization</CODE> and <CODE>performStaticDestruction</CODE> usually have much more cryptic names, and they may even be generated inline, in which case you won't see any functions for them in your object files. The important point is this: if a C++ compiler adopts this approach to the initialization and destruction of static objects, such objects will be neither initialized nor destroyed unless <CODE>main</CODE> is written in C++. Because this approach to static initialization and destruction is common, you should try to write <CODE>main</CODE> in C++ if you write any part of a software system in <NOBR>C++.<SCRIPT>create_link(22);</SCRIPT>
</NOBR></P><A NAME="36780"></A>
<P><A NAME="dingp23"></A>
Sometimes it would seem to make more sense to write <CODE>main</CODE> in C &#151; say if most of a program is in C and C++ is just a support library. Nevertheless, there's a good chance the C++ library contains static objects (if it doesn't now, it probably will in the future &#151; see<a href="./MI32_FR.HTM#5373" TARGET="_top"> Item 32</A>), so it's still a good idea to write <CODE>main</CODE> in C++ if you possibly can. That doesn't mean you need to rewrite your C code, however. Just rename the <CODE>main</CODE> you wrote in C to be <CODE>realMain</CODE>, then have the C++ version of <CODE>main</CODE> call <CODE>realMain</CODE>:<SCRIPT>create_link(23);</SCRIPT>
</P>
<A NAME="36937"></A>
<UL><PRE>
extern "C"                                // implement this
int realMain(int argc, char *argv[]);     // function in C
<A NAME="81029"></A>
int main(int argc, char *argv[])          // write this in C++
{
  return realMain(argc, argv);
}</PRE>
</UL>
<A NAME="36938"></A>
<P><A NAME="dingp24"></A>
If you do this, it's a good idea to put a comment above <CODE>main</CODE> explaining what is going <NOBR>on.<SCRIPT>create_link(24);</SCRIPT>
</NOBR></P><A NAME="36781"></A>
<P><A NAME="dingp25"></A>
If you cannot write <CODE>main</CODE> in C++, you've got a problem, because there is no other portable way to ensure that constructors and destructors for static objects are called. This doesn't mean all is lost, it just means <A NAME="p275"></A>you'll have to work a little harder. Compiler vendors are well acquainted with this problem, so almost all provide some extralinguistic mechanism for initiating the process of static initialization and static destruction. For information on how this works with your compilers, dig into your compilers' documentation or contact their <NOBR>vendors.<SCRIPT>create_link(25);</SCRIPT>
</NOBR></P>

<P><A NAME="dingp26"></A><font ID="mhtitle">Dynamic Memory Allocation</font><SCRIPT>create_link(26);</SCRIPT>
</P>

<A NAME="86064"></A>
<P><A NAME="dingp27"></A>
That brings us to dynamic memory allocation. The general rule is simple: the C++ parts of a program use <CODE>new</CODE> and <CODE>delete</CODE> (see<a href="./MI8_FR.HTM#33985"TARGET="_top"> Item 8</A>), and the C parts of a program use <CODE>malloc</CODE> (and its variants) and <CODE>free</CODE>. As long as memory that came from <CODE>new</CODE> is deallocated via <CODE>delete</CODE> and memory that came from <CODE>malloc</CODE> is deallocated via <CODE>free</CODE>, all is well. Calling <CODE>free</CODE> on a <CODE>new</CODE>ed pointer yields undefined behavior, however, as does <CODE>delete</CODE>ing a <CODE>malloc</CODE>ed pointer. The only thing to remember, then, is to segregate rigorously your <CODE>new</CODE>s and <CODE>delete</CODE>s from your <CODE>malloc</CODE>s and <CODE>free</CODE>s.<SCRIPT>create_link(27);</SCRIPT>
</P><A NAME="37117"></A>
<P><A NAME="dingp28"></A>
Sometimes this is easier said than done. Consider the humble (but handy) <CODE>strdup</CODE> function, which, though standard in neither C nor C++, is nevertheless widely <NOBR>available:<SCRIPT>create_link(28);</SCRIPT>
</NOBR></P>

<A NAME="37118"></A>
<UL><PRE>
char * strdup(const char *ps);         // return a copy of the
                                       // string pointed to by ps</PRE>
</UL>
<A NAME="37119"></A>
<P><A NAME="dingp29"></A>
If a memory leak is to be avoided, the memory allocated inside <CODE>strdup</CODE> must be deallocated by <CODE>strdup</CODE>'s caller. But how is the memory to be deallocated? By using <CODE>delete</CODE>? By calling <CODE>free</CODE>? If the <CODE>strdup</CODE> you're calling is from a C library, it's the latter. If it was written for a C++ library, it's probably the former. What you need to do after calling <CODE>strdup</CODE>, then, varies not only from system to system, but also from compiler to compiler. To reduce such portability headaches, try to avoid calling functions that are neither in the standard library (see <a href="../EC/EI49_FR.HTM#8392" TARGET="_top">Item E49</A> and <a href="./MI35_FR.HTM#5473" TARGET="_top">Item 35</A>) nor available in a stable form on most computing <NOBR>platforms.<SCRIPT>create_link(29);</SCRIPT>
</NOBR></P>

<P><A NAME="dingp30"></A><font ID="mhtitle">Data Structure Compatibility</font><SCRIPT>create_link(30);</SCRIPT>
</P>

<A NAME="36782"></A>
<P><A NAME="dingp31"></A>
Which brings us at long last to passing data between C++ and C programs. There's no hope of making C functions understand C++ features, so the level of discourse between the two languages must be limited to those concepts that C can express. Thus, it should be clear there's no portable way to pass objects or to pass pointers to member functions to routines written in C. C does understand normal pointers, however, so, provided your C++ and C compilers produce compatible output, functions in the two languages can safely exchange pointers to objects and pointers to non-member or static functions. Naturally, <A NAME="p276"></A>structs and variables of built-in types (e.g., <CODE>int</CODE>s, <CODE>char</CODE>s, etc.) can also freely cross the C++/C <NOBR>border.<SCRIPT>create_link(31);</SCRIPT>
</NOBR></P><A NAME="37222"></A>

<P><A NAME="dingp32"></A>
Because the rules governing the layout of a <CODE>struct</CODE> in C++ are consistent with those of C, it is safe to assume that a structure definition that compiles in both languages is laid out the same way by both compilers. Such structs can be safely passed back and forth between C++ and C. If you add <I>nonvirtual</I> functions to the C++ version of the struct, its memory layout should not change, so objects of a struct (or class) containing only non-virtual functions should be compatible with their C brethren whose structure definition lacks only the member function declarations. Adding <I>virtual</I> functions ends the game, because the addition of virtual functions to a class causes objects of that type to use a different memory layout (see<a href="./MI24_FR.HTM#41284" TARGET="_top"> Item 24</A>). Having a struct inherit from another struct (or class) usually changes its layout, too, so structs with base structs (or classes) are also poor candidates for exchange with C <NOBR>functions.<SCRIPT>create_link(32);</SCRIPT>
</NOBR></P><A NAME="37258"></A>

<P><A NAME="dingp33"></A>
From a data structure perspective, it boils down to this: it is safe to pass data structures from C++ to C and from C to C++ provided the definition of those structures compiles in both C++ and C. Adding nonvirtual member functions to the C++ version of a struct that's otherwise compatible with C will probably not affect its compatibility, but almost any other change to the struct <NOBR>will.<SCRIPT>create_link(33);</SCRIPT>
</NOBR></P>

<P><A NAME="dingp34"></A><font ID="mhtitle">Summary</font><SCRIPT>create_link(34);</SCRIPT>
</P>

<A NAME="37214"></A>
<P><A NAME="dingp35"></A>
If you want to mix C++ and C in the same program, remember the following simple <NOBR>guidelines:<SCRIPT>create_link(35);</SCRIPT>
</NOBR></P>
<UL><A NAME="37286"></A>
<A NAME="dingp36"></A><LI>Make sure the C++ and C compilers produce compatible object files.<SCRIPT>create_link(36);</SCRIPT>

<A NAME="37289"></A>
<A NAME="dingp37"></A><LI>Declare functions to be used by both languages <CODE>extern</CODE> <CODE>"C"</CODE>.<SCRIPT>create_link(37);</SCRIPT>

<A NAME="37290"></A>
<A NAME="dingp38"></A><LI>If at all possible, write <CODE>main</CODE> in C++.<SCRIPT>create_link(38);</SCRIPT>

<A NAME="37291"></A>
<A NAME="dingp39"></A><LI>Always use <CODE>delete</CODE> with memory from <CODE>new</CODE>; always use <CODE>free</CODE> with memory from <CODE>malloc</CODE>.<SCRIPT>create_link(39);</SCRIPT>

<A NAME="37292"></A>
<A NAME="dingp40"></A><LI>Limit what you pass between the two languages to data structures that compile under C; the C++ version of structs may contain non-virtual member functions.<SCRIPT>create_link(40);</SCRIPT>


</UL>

<DIV ALIGN="CENTER"><FONT SIZE="-1">Back to <A HREF="./MI33_FR.HTM" TARGET="_top">Item 33: Make non-leaf classes abstract</A> &nbsp;&nbsp;<BR>&nbsp;&nbsp;Continue to <A HREF="./MI35_FR.HTM" TARGET="_top">Item 35: Familiarize yourself with the language standard</A></FONT></DIV>
</BODY>
</HTML>

⌨️ 快捷键说明

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