您的位置:首页 > 编程语言

GCC-3.4.6源代码学习笔记(139)

2011-01-02 12:56 239 查看
5.12.5.2.2.2.1.3.9.


完成派生类的

RECORD_TYPE



布局


回到
finish_struct_1

中,下面的
keyed_classes

是一个保存那些在这个编译单元中将可能发布
vtable
的类的
tree_list
。这个链表中的候选者是不含有非内联、非纯虚方法的类。换而言之,是仅含有纯虚方法或(及)内联虚方法的类。对于这样的类,在每个该类定义出现的编译单元中(如,通过
#include
),应该发布其
vtable
;而对于含有其它虚方法的类,每个包含了其虚方法定义的编译单元要发布其
vtable


finish_struct_1 (continue)

5033

/* Find the key
method.
*/

5034

if (TYPE_CONTAINS_VPTR_P (t))

5035

{

5036

CLASSTYPE_KEY_METHOD (t) = key_method
(t);

5037

5038

/* If a
polymorphic class has no key method, we may emit the vtable

5039

i
n every translation unit where the class
definition appears.
*/

5040

if (CLASSTYPE_KEY_METHOD (t) == NULL_TREE)

5041

keyed_classes

= tree_cons (NULL_TREE, t, keyed_classes

);

5042

}

5043

5044

/* Layout the class
itself.
*/

5045

layout_class_type
(t, &virtuals);

5046

if (CLASSTYPE_AS_BASE (t) != t)

5047

/* We use the base type for trivial
assignments, and hence it

5048

needs a mode.
*/

5049

compute_record_mode

(CLASSTYPE_AS_BASE (t));

CLASSTYPE_KEY_METHOD
保存了类中第一个非内联及非纯虚方法
,这个域在
vtable
的产生过程中要用到。

4973

static
tree

4974

key_method

(tree type)

in class.c

4975

{

4976

tree method;

4977

4978

if (TYPE_FOR_JAVA (ty
pe)

4979

||
processing_template_decl

4980

||
CLASSTYPE_TEMPLATE_INSTANTIATION (type)

4981

||
CLASSTYPE_INTERFACE_KNOWN (type))

4982

return

NULL_TREE;

4983

4984

for
(method =
TYPE_METHODS (type); method != NULL_TREE;

4985

method = TREE_CHAIN (method))

4986

if (DECL_VINDEX (method) != NULL_TREE

4987

&& ! DECL_DECLARED_INLINE_P
(method)

4988

&& ! DECL_PURE_VIRTUAL_P
(method))

4989

return
method;

4990

4991

return
NULL_TREE;

4992

}

记住在类模板中是不允许出现虚函数的。

如果我们已经确定了是否要在该编译单元中产生
vtable

VTT

typeinfo
及其他类似的类维护数据,
CLASSTYPE_INTERFACE_KNOWN

true
,这样的类即便满足上述条件,也不应该被保存在
keyed_classes

中。

接着我们可以为类布局来决定类型的真正的大小,每个数据成员的偏移量,大小,填充字节,甚至由编译器产生的维护数据。毫无疑问,这是一个相当复杂的过程。

在深入到代码之前,我们首先看一下
GCC
为下面的例子所做的布局:


1


class
A { virtual
A* f (); };

class
B1 : virtual
public
A { virtual
B1* f (); };

class
B2 : virtual
public
A { virtual
B2* f (); };

class
C: public
B1, public
B2 { virtual
C* f (); };

int main() { return
0; }

用命令
g++ -fdump-class-hierarchy –o
test test.cc

gcc
将把关于类的信息转储到一个转储文件(如:
test.01.class
)中,我们可以看到如下的输出(暂时忽略布局以外的信息):



Class A

size=4 align=4

base size=4 base align=4

A (0xb7f2d680) 0 nearly-empty

vptr=((& A::_ZTV1A) + 8u)



Class B1

size=4 align=4

base size=4 base align=4

B1 (0xb7f2d700) 0 nearly-empty

vptridx=0u vptr=((& B1::_ZTV2B1) + 16u)

A (0xb7f2d740) 0 nearly-empty virtual

primary-for B1 (0xb7f2d700)

vptridx=4u vbaseoffset=-0x000000010



Class B2

size=4 align=4

base size=4 base align=4

B2 (0xb7f2d840) 0 nearly-empty

vptridx=0u vptr=((& B2::_ZTV2B2) + 16u)

A (0xb7f2d880) 0 nearly-empty virtual

primary-for B2 (0xb7f2d840)

vptridx=4u vbaseoffset=-0x000000010



Class C

size=8 align=4

base size=8 base align=4

C (0xb7f2d940) 0

vptridx=0u vptr=((& C::_ZTV1C) + 16u)

B1 (0xb7f2d980) 0 nearly-empty

primary-for C (0xb7f2d940)

subvttidx=4u

A (0xb7f2d9c0)
0 nearly-empty virtual

primary-for B1 (0xb7f2d980)

vptridx=20u vbaseoffset=-0x000000010

B2 (0xb7f2da00) 4 nearly-empty

lost-primary

subvttidx=12u vptridx=24u vptr=((& C::_ZTV1C) + 40u)

A (0xb7f2d9c0)
alternative-path

在输出“
A (0xb7f2d680) 0 nearly-empty
”中,“
A
”是
binfo
所来自的类,“
(0xb7f2d680)
”是
binfo
的地址,“
0
”是
binfo
在类布局中的偏移量,“
nearly-empty
”表明该类是一个几乎空的类。

而输出“
size=8 align=4
”是该类的大小及对齐量,而“
base size=8 base
align=4
”是该类的
CLASSTYPE_AS_BASE
(去除虚拟基类)的大小及对齐量。


2
(在类
A
中增加域“
int a
”):

class
A { int a; virtual
A* f (); };

class
B1 : virtual
public
A { virtual
B1* f (); };

class
B2 : virtual
public
A { virtual
B2* f (); };

class
C: public
B1, public
B2 { virtual
C* f (); };

int main() { return
0; }

其输出则是:



Class A

size=8 align=4

base size=8 base align=4

A (0xb7fae680)
0

vptr=((& A::_ZTV1A) + 8u)



Class B1

size=12 align=4

base size=4 base align=4

B1
(0xb7fae700) 0 nearly-empty

vptridx=0u vptr=((& B1::_ZTV2B1) + 12u)

A (0xb7fae740) 4 virtual

vptridx=4u vbaseoffset=-0x00000000c vptr=((& B1::_ZTV2B1) + 28u)



Class B2

size=12 align=4

base size=4 base align=4

B2
(0xb7fae800) 0 nearly-empty

vptridx=0u vptr=((& B2::_ZTV2B2) + 12u)

A (0xb7fae840) 4 virtual

vptridx=4u vbaseoffset=-0x00000000c vptr=((& B2::_ZTV2B2) + 28u)



Class C

size=16 align=4

base size=8 base align=4

C (0xb7fae8c0) 0

vptridx=0u vptr=((& C::_ZTV1C) + 12u)

B1
(0xb7fae900) 0 nearly-empty

primary-for C (0xb7fae8c0)

subvttidx=4u

A (0xb7fae940) 8 virtual

vptridx=20u vbaseoffset=-0x00000000c vptr=((& C::_ZTV1C) + 44u)

B2 (0xb7fae980) 4 nearly-empty

subvttidx=12u vptridx=24u vptr=((&
C::_ZTV1C) + 28u)

A (0xb7fae940) alternative-path

通过引入域“
int a
“,类
A
不再是一个几乎空的类,但
B1

B2
还是。这一事实深刻地影响着布局。在下面的代码中我们可以找到其原因。

4637

static
void

4638

layout_class_type

(tree t, tree
*virtuals_p)

in class.c

4639

{

4640

tree non_static_data_members;

4641

tree field;

4642

tree vptr;

4643

record_layout_info
rli;

4644

/* Maps offsets
(represented as INTEGER_CSTs) to a TREE_LIST of

4645

types that appear at that
offset.
*/

4646

splay_tree empty_base_offsets;

4647

/* True if the last
field layed out was a bit-field.
*/

4648

bool last_field_was_bitfield = false;

4649

/* The location at
which the next field should be inserted.

*/

4650

tree *next_field;

4651

/* T, as a base
class.
*/

4652

tree base_t;

4653

4654

/* Keep track of
the first non-static data member.
*/

4655

non_static_data_members = TYPE_FIELDS (t);

4656

4657

/* Start laying out
the record.
*/

4658

rli = start_record_layout
(t);

4659

4660

/* If possible, we
reuse the virtual function table pointer from one

4661

of our base classes.
*/

4662

determine_primary_base
(t);

在多继承的情况下,在派生类中基类将被依次编排。第一个基类有偏移量
0
,无疑可以从派生类的头部直接访问其成员,而其它随后的基类,要访问其成员,其成员的偏移量要加上基类本身到派生类头部的偏移量,等于包含了一个额外的间接寻址。加上深度继承的情形,需要仔细选择第一个编排的基类。注意到这里每个类定义都调用了
determine_primary_base

。如果我们为一个复杂类来调用它,其基类应该已经被这个函数处理过了。

1267

static
void

1268

determine_primary_base

(tree t)
in

class.c

1269

{

1270

int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);

1271

tree vbases;

1272

tree type_binfo;

1273

1274

/* If there are no
baseclasses, there is certainly no primary base.
*/

1275

if (n_baseclasses == 0)

1276

return
;

1277

1278

type_binfo = TYPE_BINFO (t);

1279

1280

for
(i = 0; i
< n_baseclasses; i++)

1281

{

1282

tree base_binfo = BINFO_BASETYPE
(type_binfo, i);

1283

tree basetype = BINFO_TYPE (base_binfo);

1284

1285

if (TYPE_CONTAINS_VPTR_P (basetype))

1286

{

1287

/* We prefer a
non-virtual base, although a virtual one will

1288

do.
*/

1289

if (TREE_VIA_VIRTUAL (base_binfo))

1290

continue
;

1291

1292

if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))

1293

{

1294

set_primary_base
(t, base_binfo);

1295

CLASSTYPE_VFIELDS (t) = copy_list
(CLASSTYPE_VFIELDS (basetype));

1296

}

1297

else

1298

{

1299

tree vfields;

1300

1301

/* Only add
unique vfields, and flatten them out as we go.

*/

1302

for
(vfields = CLASSTYPE_VFIELDS (basetype);

1303

vfields;

1304

vfields = TREE_CHAIN (vfields))

1305

if (VF_BINFO_VALUE (vfields) ==
NULL_TREE

1306

|| ! TREE_VIA_VIRTUAL
(VF_BINFO_VALUE (vfields)))

1307

CLASSTYPE_VFIELDS (t)

1308

= tree_cons (base_binfo,

1309

VF_BASETYPE_VALUE
(vfields),

1310

CLASSTYPE_VFIELDS
(t));

1311

}

1312

}

1313

}

含有
vtable
的非虚拟基类是最好的选择。碰到的第一个这样的基类被下面的
set_primary_base

与派生类绑定起来。注意
TYPE_VFIELD
是由编译器产生的指向
vtable
的域。

1253

static
void

1254

set_primary_base

(tree t, tree binfo)
in

class.c

1255

{

1256

tree basetype;

1257

1258

CLASSTYPE_PRIMARY_BINFO (t) = binfo;

1259

basetype = BINFO_TYPE (binfo);

1260

TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE
(basetype);

1261

TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS
(basetype);

1262

TYPE_VFIELD (t) = TYPE_VFIELD (basetype);

1263

}

上面的域
CLASSTYPE_VFIELDS
是这个类型所持有的
vtable
链表(主要及次要
vtable
)。其节点中的
TREE_VALUE
是引入这个
vtable
的类型。对于引入该
vtable
,或从其主要基类继承该
vtable
的类,节点的
TREE_PURPOSE
则是
NULL
。对于其它
vtable
(来自次要基类),其节点的
TREE_PURPOSE
是该
vtable
所来自的基类的
BINFO


注意派生类的
CLASSTYPE_VFIELDS
开始是空的;而且虚拟基类,除非它几乎是空的(这时它不可能有
vtable
),是不能作为派生类的主要基类(就算它是唯一有
vtable
的基类)。因此上面对
vtable
的拷贝能确保只对非虚拟基类进行。并且注意如果是主要基类,派生类直接拷贝其
CLASSTYPE_VFIELDS
(用于这个主要基类
vtable
的节点的
PURPOSE
域为
NULL
)。这是因为主要基类就在派生类的头部,如果其有
vtable
,这个
vtable
的地址也就是派生类
vtable
所在地址,派生类将直接把这个
vtable
据为己有。

determine_primary_base (continue)

1315

if (!TYPE_VFIELD (t))

1316

CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;

1317

1318

/* Find the
indirect primary bases - those virtual bases which are primary

1319

bases of something else in
this hierarchy.

*/

1320

for
(vbases = CLASSTYPE_VBASECLASSES (t);

1321

vbases;

1322

vbases = TREE_CHAIN (vbases))

1323

{

1324

tree vbase_binfo = TREE_VALUE (vbases);

1325

1326

/* See if this
virtual base is an indirect primary base. To be so,

1327

it must be a primary base
within the hierarchy of one of our

1328

direct bases.
*/

1329

for
(i = 0;
i < n_baseclasses; ++i)

1330

{

1331

tree basetype = TYPE_BINFO_BASETYPE (t,
i);

1332

tree v;

1333

1334

for
(v =
CLASSTYPE_VBASECLASSES (basetype);

1335

v;

1336

v = TREE_CHAIN (v))

1337

{

1338

tree base_vbase = TREE_VALUE (v);

1339

1340

if (BINFO_PRIMARY_P (base_vbase)

1341

&& same_type_p (BINFO_TYPE
(base_vbase),

1342

BINFO_TYPE (vbase_binfo)))

1343

{

1344

BINFO_INDIRECT_PRIMARY_P
(vbase_binfo) = 1;

1345

break
;

1346

}

1347

}

1348

1349

/* If we've
discovered that this virtual base is an indirect

1350

primary base, then we can move on to the
next virtual

1351

base.

*/

1352

if (BINFO_INDIRECT_PRIMARY_P
(vbase_binfo))

1353

break
;

1354

}

1355

}

1356

1357

/* A
"nearly-empty" virtual base class can be the primary base

1358

class, if no non-virtual polymorphic
base can be found.
*/

1359

if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))

1360

{

1361

/* If not NULL,
this is the best primary base candidate we have

1362

found so far.
*/

1363

tree candidate = NULL_TREE;

1364

tree base_binfo;

1365

1366

/* Loop over the
baseclasses.

*/

1367

for
(base_binfo = TYPE_BINFO (t);

1368

base_binfo;

1369

base_binfo = TREE_CHAIN (base_binfo))

1370

{

1371

tree basetype = BINFO_TYPE (base_binfo);

1372

1373

if (TREE_VIA_VIRTUAL (base_binfo)

1374

&& CLASSTYPE_NEARLY_EMPTY_P
(basetype))

1375

{

1376

/* If this is not an indirect primary base,
then it's

1377

definitely our primary
base.
*/

1378

if (!BINFO_INDIRECT_PRIMARY_P (base_binfo))

1379

{

1380

candidate = base_binfo;

1381

break
;

1382

}

1383

1384

/* If this is
an indirect primary base, it still could be

1385

our primary base --
unless we later find there's another

1386

nearly-empty virtual base that isn't an
indirect

1387

primary base.
*/

1388

if (!candidate)

1389

candidate = base_binfo;

1390

}

1391

}

1392

1393

/* If we've got a
primary base, use it.
*/

1394

if (candidate)

1395

{

1396

set_primary_base
(t, candidate);

1397

CLASSTYPE_VFIELDS (t)

1398

= copy_list (CLASSTYPE_VFIELDS
(BINFO_TYPE (candidate)));

1399

}

1400

}

1401

1402

/* Mark the primary
base classes at this point.
*/

1403

mark_primary_bases
(t);

1404

}

如果没有找到含有
vtable
的非虚拟基类,派生类的
TYPE_VFIELD
保持为
NULL
(在
set_primary base

中,它会被设置为主要基类的
TYPE_VFIELD
),这时不管以前把
CLASSTYPE_PRIMARY_BINFO
设置成什么,把它置为
NULL
。接着看看能不能在虚拟基类中找到可以作为主要基类的。能作为主要基类的虚拟基类,除了需要是几乎空的之外,没有被用作其基类的主要基类是优先考虑的,否则就将就使用在派生类声明中最后出现的虚拟基类(这样也减少了冲突的机会)。

严格来说,在一个派生类中只有一个主要基类。例如:

class
A {…}; class
B: public
A {…}; class
C: public
B {…};

此中类
B
的主要基类是
A
。而在类
C
中,主要基类是
B
,不再是
A
。但是
C
中关于
B

binfo
是从类
B
中拷贝过来的,拷贝时没有拷入关于主要基类的信息。不过虚拟基类则不然,下面的函数还会对它进行“拨乱反正”。

1218

static
void

1219

mark_primary_bases

(tree type)
in

class.c

1220

{

1221

tree binfo;

1222

1223

/* Walk the bases
in inheritance graph order.
*/

1224

for
(binfo =
TYPE_BINFO (type); binfo; binfo = TREE_CHAIN (binfo))

1225

{

1226

tree base_binfo = get_primary_binfo
(binfo);

1227

1228

if (!base_binfo)

1229

/* Not a
dynamic base.
*/
;

1230

else if (BINFO_PRIMARY_P (base_binfo))

1231

BINFO_LOST_PRIMARY_P (binfo) = 1;

1232

else

1233

{

1234

BINFO_PRIMARY_BASE_OF (base_binfo) =
binfo;

1235

/* A virtual
binfo might have been copied from within

1236

another hierarchy. As we're about to use
it as a primary

1237

base, make
sure the offsets match.
*/

1238

if (TREE_VIA_VIRTUAL (base_binfo))

1239

{

1240

tree delta = size_diffop (convert
(ssizetype,

1241

BINFO_OFFSET
(binfo)),

1242

convert (ssizetype,

1243

BINFO_OFFSET
(base_binfo)));

1244

1245

propagate_binfo_offsets
(base_binfo, delta);

1246

}

1247

}

1248

}

1249

}


1226
行的
get_primary_binfo

返回参数
binfo

所对应类型的主要基类的
binfo
的拷贝,如果设置了主要基类的话;否则返回
NULL


6470

tree

6471

get_primary_binfo

(tree binfo)
in

class.c

6472

{

6473

tree primary_base;

6474

tree result;

6475

6476

primary_base = CLASSTYPE_PRIMARY_BINFO
(BINFO_TYPE (binfo));

6477

if (!primary_base)

6478

return
NULL_TREE;

6479

6480

result = copied_binfo
(primary_base, binfo);

6481

return
result;

6482

}

copied_binfo

根据给定的
primary_base

,从
binfo

中找出对应的部分。考虑以下例子:

class
A { virtual
… };

class
B: public
A { virtual
… };

class
C: public
A { virtual
… };

class
D: public
B, C { … };

首先,在
mark_primary_bases


1224
行,
TYPE_BINFO(D)
得到一个链表,其中依次是
D
à

B
à

A
à

C
à

A
。显然,
CLASSTYPE_PRIMARY_BINFO(D)
返回
B

binfo
拷贝(它由
set_primary_base

设置);然后在下面的
2578
行,递归进入
copied_binfo

并得到
D

binfo
,接着在
2581
行的
FOR
循环中,在
D
的基类
B

C
中查找,找出目标
B
。因为该
B

binfo
拷贝来自类
B

1230
行的
BINFO_PRIMARY_P (base_binfo)
返回
NULL
,这表示
B
不是主要基类(但现在是!)。因此在
1234
行,我们把它设为
D
的主要基类(注意与
CLASSTYPE_PRIMARY_BINFO
的区别)。

那么对于
B

binfo

A
是其主要基类。在
D
中查找
A

binfo
拷贝与查找
B

binfo
拷贝类似,除了在
D

A
同时出现在
B

C
中。不过查找的过程能保证找到的是
B
à

A
。因为
A
是类
B
的主要基类,但在
A
拷贝的
binfo
中,并没有设置
BINFO_PRIMARY_P
,它满足
1232
行条件,被设置为
B
的拷贝
binfo
的主要基类。

同样的我们可以得到
D

C
部分的
A

binfo
拷贝,并且它也没有设置
BINFO_PRIMARY_P


2556

tree

2557

copied_binfo

(tree binfo, tree here)
in

search.c

2558

{

2559

tree result = NULL_TREE;

2560

2561

if (TREE_VIA_VIRTUAL (binfo))

2562

{

2563

tree t;

2564

2565

for
(t = here; BINFO_INHERITANCE_CHAIN (t);

2566

t = BINFO_INHERITANCE_CHAIN (t))

2567

continue
;

2568

2569

result = purpose_member (BINFO_TYPE
(binfo),

2570

CLASSTYPE_VBASECLASSES (BINFO_TYPE (t)));

2571

result = TREE_VALUE (result);

2572

}

2573

else if (BINFO_INHERITANCE_CHAIN (binfo))

2574

{

2575

tree base_binfos;

2576

int
ix, n;

2577

2578

base_binfos = copied_binfo
(BINFO_INHERITANCE_CHAIN (binfo), here);

2579

base_binfos = BINFO_BASETYPES
(base_binfos);

2580

n = TREE_VEC_LENGTH (base_binfos);

2581

for
(ix =
0; ix != n; ix++)

2582

{

2583

tree base = TREE_VEC_ELT (base_binfos,
ix);

2584

2585

if (BINFO_TYPE (base) == BINFO_TYPE
(binfo))

2586

{

2587

result = base;

2588

break
;

2589

}

2590

}

2591

}

2592

else

2593

{

2594

my_friendly_assert (BINFO_TYPE (here) ==
BINFO_TYPE (binfo), 20030202);

2595

result = here;

2596

}

2597

2598

my_friendly_assert (result, 20030202);

2599

return
result;

2600

}

进一步考虑如下的例子:

class
A { virtual
…};

class
B: virtual
public
A { … };

class
C: virtual
public
A { … };

class
D: public
B, C { … };


TYPE_BINFO(D)
链表中,依次是
D
à

B
à

A
à

C
,因为
A
作为虚拟基类在
D
中只能维持一个实例。这个过程是几乎相同的,除了查找虚拟基类的
binfo
拷贝时,是从继承树顶开始向下,而不是从基类开始往上爬。另外,由于虚拟基类
A
不使用拷贝
binfo
,因此在
mark_primary_bases

中,它满足
1230
行条件。


copy_base_binfos

中,连同
binfo
拷贝的还有偏移量信息。不过这个偏移量是关于被拷贝的
binfo
。而作为主要基类,虚拟基类(也包括非虚拟基类)必须被放在布局的最前面(事实上紧跟着
vtable
)。这个调整由
propagate_binfo_offsets

来完成(对于非虚拟的基类
binfo
,它的偏移量一直是
0
,并且在当前类中编排该基类时,其非虚拟基类也维持着不变的相对偏移量)。

4355

static
void

4356

propagate_binfo_offsets

(tree binfo,
tree offset)
in

class.c

4357

{

4358

int i;

4359

tree primary_binfo;

4360

4361

/* Update BINFO's offset.
*/

4362

BINFO_OFFSET (binfo)

4363

= convert (sizetype,

4364

size_binop (PLUS_EXPR,

4365

convert (ssizetype,
BINFO_OFFSET (binfo)),

4366

offset));

4367

4368

/* Find the primary
base class.
*/

4369

primary_binfo = get_primary_binfo
(binfo);

4370

4371

/* Scan all of the
bases, pushing the BINFO_OFFSET adjust

4372

downwards.

*/

4373

for
(i = -1; i < BINFO_N_BASETYPES (binfo); ++i)

4374

{

4375

tree base_binfo;

4376

4377

/* On the first
time through the loop, do the primary base.

4378

Because the primary base
need not be an immediate base, we

4379

must handle the primary base
specially.
*/

4380

if (i == -1)

4381

{

4382

if (!primary_binfo)

4383

continue
;

4384

4385

base_binfo = primary_binfo;

4386

}

4387

else

4388

{

4389

base_binfo = BINFO_BASETYPE (binfo, i);

4390

/* Don't do the
primary base twice.
*/

4391

if (base_binfo == primary_binfo)

4392

continue
;

4393

}

4394

4395

/* Skip virtual
bases that aren't our canonical primary base.

*/

4396

if (TREE_VIA_VIRTUAL (base_binfo)

4397

&& BINFO_PRIMARY_BASE_OF
(base_binfo) != binfo)

4398

continue
;

4399

4400

propagate_binfo_offsets
(base_binfo, offset);

4401

}

4402

}

函数
propagate_binfo_offsets

把偏移量的调整应用到整个基类。记得
BINFO_OFFSET
表示该基类在其派生类中的偏移量。前面看到主要基类不一定是直接基类,因此
4373
行的
FOR
循环需要多一次计数来包括可能不是直接基类的主要基类。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: