没有合适的资源?快使用搜索试试~ 我知道了~
C++ under the Hood--Jan Gray.pdf (learning sbout c++ compiler)
需积分: 9 28 下载量 143 浏览量
2009-04-29
13:50:17
上传
评论
收藏 127KB PDF 举报
温馨提示
试读
23页
author introduction: Jan Gray is a Software Design Engineer in Microsoft’s Visual C++ Business Unit. He helped design and implement the Microsoft Visual C++ compiler. book introduction: It is important to understand how your programming language is implemented. Such knowledge dispels the fear and wonder of “What on earth is the compiler doing here?”; imparts confidence to use the new features; and provides insight when debugging and learning other language features. It also gives a feel for the relative costs of different coding choices that is necessary to write the most efficient code day to day.
资源推荐
资源详情
资源评论
The original article is taken from http://msdn.microsoft.com/archive/en-
us/dnarvc/html/jangrayhood.asp. Illustrations are taken from
http://www.microsoft.com/japan/msdn/vs_previous/visualc/techmat/feature/jangrayhood/.
Archived content. No warranty is made as to technical accuracy. Content may contain
URLs that were valid when originally published, but now link to sites or pages that no
longer exist.
Visual C and C++ (General) Technical Articles
C++: Under the Hood
Jan Gray
March 1994
Jan Gray is a Software Design Engineer in Microsoft’s Visual C++ Business Unit. He helped
design and implement the Microsoft Visual C++ compiler.
Introduction
It is important to understand how your programming language is implemented. Such
knowledge dispels the fear and wonder of “What on earth is the compiler doing here?”;
imparts confidence to use the new features; and provides insight when debugging and
learning other language features. It also gives a feel for the relative costs of different
coding choices that is necessary to write the most efficient code day to day.
This paper looks “under the hood” of C++, explaining “run-time” C++ implementation
details such as class layout techniques and the virtual function call mechanism. Questions
to be answered include:
• How are classes laid out?
• How are data members accessed?
• How are member functions called?
• What is an adjuster thunk?
• What are the costs:
• Of single, multiple, and virtual inheritance?
• Of virtual functions and virtual function calls?
• Of casts to bases, to virtual bases?
• Of exception handling?
First, we’ll look at struct layout of C-like structs, single inheritance, multiple inheritance,
and virtual inheritance, then consider data member access and member functions, virtual
and not. We’ll examine the workings of constructors, destructors, and assignment operator
special member functions and dynamic construction and destruction of arrays. Finally, we’ll
briefly consider the impact of exception-handling support.
For each language feature topic, we’ll very briefly present motivation and semantics for the
language feature (although “Introduction to C++” this is not), and examine how the
language feature was implemented in Microsoft® Visual C++™. Note the distinction
between abstract language semantics and a particular concrete implementation. Other
vendors have sometimes made different implementation choices for whatever reasons. In a
few cases we contrast the Visual C++ implementation with others.
Class Layout
In this section we’ll consider the storage layouts required for different kinds of inheritance.
C-like Structs
As C++ is based upon C, it is “mostly” upwards-compatible with C. In particular, the
working papers specify the same simple struct layout rules that C has: Members are laid
out in their declaration order, subject to implementation defined alignment padding. All
C/C++ vendors ensure that valid C structs are stored identically by their C and C++
compilers. Here A is a simple C struct with the obvious expected member layout and
padding.
struct A {
char c;
int i;
};
C-like Structs with C++ Features
Of course, C++ is an object-oriented programming language: It provides inheritance,
encapsulation, and polymorphism by extending the mundane C struct into the wondrous
C++ class. Besides data members, C++ classes can also encapsulate member functions
and many other things. However, except for hidden data members introduced to
implement virtual functions and virtual inheritance, the instance size is solely determined
by a class’s data members and base classes.
Here B is a C-like struct with some C++ features: There are public/protected/private access
control declarations, member functions, static members, and nested type declarations.
Only the non-virtual data members occupy space in each instance. Note that the standards
committee working papers permit implementations to reorder data members separated by
an access declarator, so these three members could have been laid out in any order. (In
Visual C++, members are always laid out in declaration order, just as if they were
members of a C struct)
struct B {
public:
int bm1;
protected:
int bm2;
private:
int bm3;
static int bsm;
void bf();
static void bsf();
typedef void* bpv;
struct N { };
};
Single Inheritance
C++ provides inheritance to factor out and share common aspects of different types. A
good example of a classes-with-inheritance data type organization is biology’s classification
of living things into kingdoms, phyla, orders, families, genus, species, and so on. This
organization makes it possible to specify attributes, such as “mammals bear live young” at
the most appropriate level of classification; these attributes are then inherited by other
classes, so we can conclude without further specification that whales, squirrels, and people
bear live young. Exceptional cases, such as platypi (a mammal, yet lays eggs), will require
that we override the inherited attribute or behavior with one more appropriate for the
derived class. More on that later.
In C++, inheritance is specified by using the “: base” syntax when defining the derived
class. Here D is derived from its base class C.
struct C {
int c1;
void cf();
};
struct D : C {
int d1;
void df();
};
Since a derived class inherits all the properties and behavior of its base class, each
instance of the derived class will contain a complete copy of the instance data of the base
class. Within D, there is no requirement that C’s instance data precede D’s. But by laying D
out this way, we ensure that the address of the C object within D corresponds to the
address of the first byte of the D object. As we shall see, this eliminates adding a
displacement to a D* when we need to obtain the address of its embedded C. This layout is
used by all known C++ implementations. Thus, in a single inheritance class hierarchy, new
instance data introduced in each derived class is simply appended to the layout of the base
class. Note our layout diagram labels the “address points” of pointers to the C and D objects
within a D.
Multiple Inheritance
Single inheritance is quite versatile and powerful, and generally adequate for expressing
the (typically limited) degree of inheritance present in most design problems. Sometimes,
however, we have two or more sets of behavior that we wish our derived class to acquire.
C++ provides multiple inheritance to combine them.
For instance, say we have a model for an organization that has a class Manager (who
delegates) and class
Worker (who actually does the work). Now how can we model a class
MiddleManager, who, like a Worker, accepts work assignments from his/her manager and who,
like a
Manager, delegates this work to his/her employees? This is awkward to express using
single inheritance: For MiddleManager to inherit behavior from both Manager and Worker, both
must be base classes. If this is arranged so that MiddleManager inherits from Manager which
inherits from Worker, it erroneously ascribes Worker behavior to Managers. (Vice versa, the
same problem.) Of course, MiddleManager could inherit from just one (or neither) of Worker or
Manager, and instead, duplicate (redeclare) both interfaces, but that defeats polymorphism,
fails to reuse the existing interface, and leads to maintenance woes as interfaces evolve
over time.
Instead, C++ allows a class to inherit from multiple base classes:
struct Manager ... { ... };
struct Worker ... { ... };
struct MiddleManager : Manager, Worker { ... };
How might this be represented? Continuing with our “classes of the alphabet” example:
struct E {
int e1;
void ef();
};
struct F : C, E {
int f1;
void ff();
};
Struct F multiply inherits from C and E. As with single inheritance, F contains a copy of the
instance data of each of its base classes. Unlike single inheritance, it is not possible to
make the address point of each bases’ embedded instance correspond to the address of the
derived class:
F f;
// (void*)&f == (void*)(C*)&f;
// (void*)&f < (void*)(E*)&f;
剩余22页未读,继续阅读
资源评论
Jerry1109
- 粉丝: 3
- 资源: 6
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功