读《深度探索C++对象模型》(简体版)的两个疑问

boodweb 2002-02-22 10:38:02
读《深度探索C++对象模型》(简体版)的两个疑问
疑问一:
  p.105讲述了继承对象的布局为什么不紧凑(即除去多余的填补空间),书上说是因为要防止在进行对象赋值间时出现意外。但是我搞不清书上的例子为什么会产生意外,以书上的例子来说:
Concrete2 *pc2;
Concrete1 *pc1_1,*pc1_2;
pc1_1 = pc2; //pc1_1指向Concrete2对象
*pc1_2=*pc1_1; //将Concrete2赋给Concrete1

若采取紧凑的布局,则布局应该这样:
_____________ ____________
| | | |
| int 4 | | int 4 |
|----------| |----------|
| char 1 | | char 1 |
|----------| |----------|
| | | char 1 |
| padding | |----------|
| 3 | | padding2 |
|__________| |__________|
Concrete1 Concrete2

  但此时将Concrete2赋给Concrete1并不会发生任何问题啊,只会将Concrete1的一个padding字节用Concrete2的下面一个char覆盖,除非把Concrete1赋给Concrete2才会将Concrete2下面的一个char用未知数据填充,造成书上所说的情况。这样的话书上例子就应该改成:
Concrete2 *pc2;
Concrete1 *pc1_1,*pc1_2;
pc1_1 = pc2; //pc1_1指向Concrete2对象
*pc1_1=*pc1_2; //将Concrete1赋给Concrete2(改)
~~~ ~~~ ~~ ~~

  不知道我想的对不对。


疑问二:
  p.148讲述的是static member functions(静态成员函数)的由来,作者说是要便于存取static members(静态成员变量),但是static members不是可以直接用“::”存取吗,干吗还要static member functions呢?
...全文
54 20 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
boodweb 2002-08-26
  • 打赏
  • 举报
回复
看来解决不了了,结账
magicblue 2002-02-27
  • 打赏
  • 举报
回复
> 但此时将Concrete2赋给Concrete1并不会发生任何问题啊,只会将Concrete1的一个padding字节用Concrete2的下面一个char覆盖

但是这个char被指定了一个值,原先的数值被覆盖

另外从概念上讲没人会这么做吧:*pc1_1=*pc1_2;
magicblue 2002-02-27
  • 打赏
  • 举报
回复
是没关系,可是会使覆盖掉对齐字节的char被重赋值。

两个指针类型相同但指向不同,char这个数据成员被覆盖掉,没了

如果还有疑问考虑一下转型
boodweb 2002-02-27
  • 打赏
  • 举报
回复
To magicblue(小飞侠):
对于书上的代码,在紧凑布局的情况下,pc1_2指向Concrete1,其被覆盖的地方原先并没有数值,那里只是padding的字节啊,覆盖掉又有什么关系?

>另外从概念上讲没人会这么做吧:*pc1_1=*pc1_2;
我觉得这么说不对,两个指针类型相同,都是Concrete1*,凭什么不能这么赋值呢?
magicblue 2002-02-26
  • 打赏
  • 举报
回复
回答你第一个问题:
书中的覆盖之意是值的“覆盖”。并非一个char的数据成员被覆盖掉了。COPY的对象的char会被指定一个值,不是我们所期望的
boodweb 2002-02-26
  • 打赏
  • 举报
回复
况且还有两个地方和我的相印证:一是侯捷书上的注释的那个箭头(p.106下面)也是从Concrete1指向Concrete2的;二是p.106上部的代码注释中有这么一句:“喔欧:derived class subobject被覆盖掉”,这个“derived class”也应该指的是Concrete2,那么原文的将Concrete2赋给Concrete1更是没有道理了。
boodweb 2002-02-25
  • 打赏
  • 举报
回复
真没想到,还是。。。看来我要想办法作张图了
我先用文字叙述一下吧,Concrete2继承自Concrete1,比后者多了一个char,注意这是紧凑布局,不是真的C++实现:
对象Concrete1结构(从上到下):
一个int(4字节)
一个char(1字节)
padding(3字节)

对象Concrete2结构(从上到下):
一个int(4字节)
一个char(1字节)
一个char(1字节)
padding(2字节)

真的C++实现是这样的:
对象Concrete2结构(从上到下):
一个int(4字节)
一个char(1字节)
padding(3字节)
一个char(1字节)
padding(3字节)
boodweb 2002-02-25
  • 打赏
  • 举报
回复
只能这样了,其中"*"号只是起了代替空格的作用,不然又要和第一次贴的一样了,好像CSDN喜欢吃空格:
__________________________
|**********|**|**********|
|**int*4***|**|**int*4***|
|----------|**|----------|
|**char*1**|**|**char*1**|
|----------|**|----------|
|**********|**|**char*1**|
|*padding**|**|----------|
|****3*****|**|*padding2*|
|__________|**|__________|
**Concrete1*****Concrete2

另外,我发现即使把文字像我那样改了还是有问题,因为如果那样的话就会将一个Concrete1赋给Concrete2,那么就算在实际的情形里(即不压缩掉多余的填补控件),Concrete1也会被扩充成Concrete2,但是Concrete1中本来就没有定义Concrete2中下面的那个char,因此不管在哪种情况里,得到的Concrete2的下面的那个char都是未定义的。
tpProgramer 2002-02-25
  • 打赏
  • 举报
回复
boodweb(TTT) :

不是我不回答你,是因为你的图画得实在有点...

你说的那章我看过,但是现在我在公司,书不在手上,所以没有办法考证你的看法,
我想那本书上说得应该没有问题,不过也不排除侯sir出错的可能,我回去看看再回答你.
tpProgramer 2002-02-23
  • 打赏
  • 举报
回复
langzi8818(涂春银) :
对, 因为本身这个静态变量只有一个实例,而且跟这个类有没有实例无关.
你可以认为类中的静态变量就是一个有作用域的特殊的全局静态变量.
langzi8818 2002-02-23
  • 打赏
  • 举报
回复
如果在类中声明了一个静态变量,那么所有改类的实例都可以访问它,而且可以改变它。(初学者,不只对不对:))
tpProgramer 2002-02-23
  • 打赏
  • 举报
回复
我真服了CSDN的排版了!! 重来:

#include <iostream>

using namespace std;
class CMyClass {
public:
static int m_i;
};

int CMyClass::m_i = 0;

void main() {
CMyClass a,b;
cout << a.m_i << endl;
cout << b.m_i << endl;
a.m_i = 1;
cout << a.m_i << endl;
cout << b.m_i << endl;
}

Output
0
0
1
1
tpProgramer 2002-02-23
  • 打赏
  • 举报
回复
对于这个问题,应该如下访问才对,请看代码:

#include<iostream>

usingnamespacestd;

classA
{
public:
staticlongn;
};

longA::n=100;

voidmain(void)
{
classAa;
cout<<A::n;
cin.get();
}
boodweb 2002-02-23
  • 打赏
  • 举报
回复
To tpProgrammer:
那我在疑问一中的想法到底对不对呢?
rain_cloud 2002-02-22
  • 打赏
  • 举报
回复
每一个问题是为了保证类的架构不会变化
gigix 2002-02-22
  • 打赏
  • 举报
回复
第一个问题好长哦……

第二个问题:这是个数据封装的问题。任何对象都不应该暴露自己的数据,而应该通过access方法来访问数据,记得吗?
snipersu 2002-02-22
  • 打赏
  • 举报
回复
当你的静态成员是私有的话,对其进行操作就应当用静态成员函数。
snipersu 2002-02-22
  • 打赏
  • 举报
回复
当你的静态成员是私有的话,对其进行操作就应当用静态成员函数。
boodweb 2002-02-22
  • 打赏
  • 举报
回复
wk,图像怎么变成这样了,自己看书上106页侯捷的注释吧
boodweb 2002-02-22
  • 打赏
  • 举报
回复
To snipersu:
那如果是public的是否就可以这样访问了呢?我用VC 6.0试了一下好像不行,不过我记得看C++书的时候是可以这样访问的啊:
#include <iostream.h>
#include "stdio.h"
class Point2d
{
public:
static int z;
};
void main()
{
Point2d::z=1;
}
stltest.obj : error LNK2001: unresolved external symbol "public: static int Point2d::z" (?z@Point2d@@2HA)
Debug/STLTEST.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.

To gigix:
这倒没错!

70,023

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧