📄 mi24.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>More Effective C++ | Item 24: Understand the costs of virtual functions, multiple inheritance, virtual base classes, and RTTI</TITLE>
<LINK REL=STYLESHEET HREF=../INTRO/ECMEC.CSS>
<SCRIPT LANGUAGE="Javascript" SRC="../JAVA/COOKIE.JS"></SCRIPT>
<SCRIPT LANGUAGE="Javascript">var imagemax = 9; setCurrentMax(9);</SCRIPT>
<SCRIPT LANGUAGE="Javascript" SRC="../JAVA/IMGDOC.JS"></SCRIPT>
<SCRIPT LANGUAGE="Javascript" SRC="../JAVA/NSIMGDOC.JS"></SCRIPT>
<SCRIPT LANGUAGE="Javascript" SRC="../JAVA/DINGBATS.JS"></SCRIPT>
<SCRIPT LANGUAGE="Javascript">
var dingbase = "MI24_DIR.HTM";
var dingtext = "Item M24, P";
if (self == top) {
top.location.replace(dingbase + this.location.hash);
}
</SCRIPT>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" ONLOAD="setResize()">
<!-- SectionName="M24: Costs of various language features" -->
<A NAME="41284"></A>
<DIV ALIGN="CENTER"><FONT SIZE="-1">Back to <A HREF="./MI23_FR.HTM" TARGET="_top">Item 23: Consider alternative libraries</A> <BR> Continue to <A HREF="./MTECH_FR.HTM" TARGET="_top">Techniques</A></FONT></DIV>
<P><A NAME="dingp1"></A><font ID="mititle">Item 24: Understand the costs of virtual functions, multiple inheritance, virtual base classes, and RTTI.</font><SCRIPT>create_link(1);</SCRIPT>
</P>
<A NAME="72158"></A>
<A NAME="41285"></A>
<P><A NAME="dingp2"></A>
C++ compilers must find a way to implement each feature in the language. Such implementation details are, of course, compiler-dependent, and different compilers implement language features in different ways. For the most part, you need not concern yourself with such matters. However, the implementation of some features can have a noticeable impact on the size of objects and the speed at which member functions execute, so for those features, it's important to have a basic understanding of what compilers are likely to be doing under the hood. The foremost example of such a feature is virtual <NOBR>functions.<SCRIPT>create_link(2);</SCRIPT>
</NOBR></P><A NAME="41289"></A>
<P><A NAME="dingp3"></A>
When a virtual function is called, the code executed must correspond to the <A HREF="./MIINTRFR.HTM#72671" TARGET="_top">dynamic type</a> of the object on which the function is invoked; the type of the pointer or reference to the object is immaterial. How can compilers provide this behavior efficiently? Most implementations use <I>virtual tables</I> and <I>virtual table pointers</I>. Virtual tables and virtual table pointers are commonly referred to as <I>vtbls</I> and <I>vptrs</I>, <NOBR>respectively.<SCRIPT>create_link(3);</SCRIPT>
</NOBR></P><A NAME="9490"></A>
<P><A NAME="dingp4"></A>
A vtbl is usually an array of pointers to functions. (Some compilers use a form of linked list instead of an array, but the fundamental strategy is the same.) Each class in a program that declares or inherits virtual functions has its own vtbl, and the entries in a class's vtbl are pointers to the implementations of the virtual functions for that class. For example, given a class definition like <NOBR>this,<SCRIPT>create_link(4);</SCRIPT>
</NOBR></P>
<A NAME="41291"></A>
<UL><PRE><A NAME="p114"></A>class C1 {
public:
C1();
<A NAME="62347"></A>
virtual ~C1();
virtual void f1();
virtual int f2(char c) const;
virtual void f3(const string& s);
<A NAME="41292"></A>
void f4() const;
<A NAME="41293"></A>
...
};
</PRE>
</UL>
<A NAME="41311"></A>
<P><A NAME="dingp5"></A><CODE>C1</CODE>'s virtual table array will look something like <NOBR>this:<SCRIPT>create_link(5);</SCRIPT>
</NOBR></P>
<SPAN ID="Image1of1" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_114A1.GIF" BORDER=0></SPAN>
<SPAN ID="Image1of2" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_114A2.GIF" BORDER=0></SPAN>
<SPAN ID="Image1of3" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_114A3.GIF" BORDER=0></SPAN>
<SPAN ID="Image1of4" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_114A4.GIF" BORDER=0></SPAN>
<SPAN ID="Image1of5" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_114A5.GIF" BORDER=0></SPAN>
<SPAN ID="Image1of6" STYLE="position: relative; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_114A5.GIF" BORDER=0></SPAN>
<A NAME="42364"></A>
<P><A NAME="dingp6"></A>
Note that the nonvirtual function <CODE>f4</CODE> is not in the table, nor is <CODE>C1</CODE>'s constructor. Nonvirtual functions — including constructors, which are by definition nonvirtual — are implemented just like ordinary C functions, so there are no special performance considerations surrounding their <NOBR>use.<SCRIPT>create_link(6);</SCRIPT>
</NOBR></P>
<A NAME="42369"></A>
<P><A NAME="dingp7"></A>
If a class <CODE>C2</CODE> inherits from <CODE>C1</CODE>, redefines some of the virtual functions it inherits, and adds some new ones of its <NOBR>own,<SCRIPT>create_link(7);</SCRIPT>
</NOBR></P>
<A NAME="42365"></A>
<UL><PRE>class C2: public C1 {
public:
C2(); // nonvirtual function
virtual ~C2(); // redefined function
virtual void f1(); // redefined function
virtual void f5(char *str); // new virtual function
...
};
</PRE>
</UL>
<A NAME="42380"></A>
<P><A NAME="dingp8"></A>its virtual table entries point to the functions that are appropriate for objects of its type. These entries include pointers to the <CODE>C1</CODE> virtual functions that <CODE>C2</CODE> chose not to <NOBR>redefine:<SCRIPT>create_link(8);</SCRIPT>
</NOBR></P>
<SPAN ID="Image2of1" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_114B1.GIF" BORDER=0></SPAN>
<SPAN ID="Image2of2" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_114B2.GIF" BORDER=0></SPAN>
<SPAN ID="Image2of3" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_114B3.GIF" BORDER=0></SPAN>
<SPAN ID="Image2of4" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_114B4.GIF" BORDER=0></SPAN>
<SPAN ID="Image2of5" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_114B5.GIF" BORDER=0></SPAN>
<SPAN ID="Image2of6" STYLE="position: relative; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_114B5.GIF" BORDER=0></SPAN>
<A NAME="42346"></A>
<P><A NAME="dingp9"></A>
This discussion brings out the first cost of virtual functions: you have to set aside space for a virtual table for each class that contains virtual <A NAME="p115"></A>functions. The size of a class's vtbl is proportional to the number of virtual functions declared for that class (including those it inherits from its base classes). There should be only one virtual table per class, so the total amount of space required for virtual tables is not usually significant, but if you have a large number of classes or a large number of virtual functions in each class, you may find that the vtbls take a significant bite out of your address <NOBR>space.<SCRIPT>create_link(9);</SCRIPT>
</NOBR></P><A NAME="62642"></A>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -