现在的位置: 首页 > 综合 > 正文

C++ 对象模型学习记录(2)— 第3章 data语义学

2013年04月21日 ⁄ 综合 ⁄ 共 4618字 ⁄ 字号 评论关闭

1. 关于sizeof的运行结果

#include <iostream>
//在GCC 中
using namespace std;
class X{};
class Y :public X{};
class Z : public X{};
class W :public Y,public Z{};
int main()
{
cout
<< sizeof(X) << endl;//1
cout
<< sizeof(Y) << endl;//1
cout
<< sizeof(Z) << endl;//1
cout
<< sizeof(W) << endl;//2
return 0;
}

  而在vs 2010中是默认的编译器中

#include <iostream>

using namespace std;
class X{};
class Y :public X{};
class Z : public X{};
class W :public Y,public Z{};
int main()
{
cout
<< sizeof(X) << endl;//1
cout << sizeof(Y) << endl;//1
cout << sizeof(Z) << endl;//1
cout << sizeof(W) << endl;//1
return 0;
}

  加了虚继承后,GCC和vs的竟然相同了,总的来说就是有了 virtual 继承,加了一个vptr指针和指向的是一个 要么是virtual base table,要么是offset

#include <iostream>

using namespace std;
class X{};
class Y :public virtual X{};
class Z : public virtual X{};
class W :public Y,public Z{};
int main()
{
cout
<< sizeof(X) << endl;//1
cout << sizeof(Y) << endl;;//4
cout << sizeof(Z) << endl;//4
cout << sizeof(W) << endl;//8
return 0;
}

 2. 关于指向data member 数据成员的指针

#include <iostream>
#include
<stdio.h>
using namespace std;
struct Base1{int val1; };
struct Base2{int val2; };
struct Derived : Base1,Base2 {};
//Derived2为了和Derived比较
struct Derived2 : Base1,Base2{int val3;};
void func1(int Derived::*dmp,Derived *pd)
{
//期望传进来的是一个"指向 derived class 的member "的指针
//如果传进来的是“指向base class 的member”的指针,
//结果如何?
cout << pd->*dmp << endl;
}
void func2(Derived *pd)
{
//bmp将成为1
int Base2::* bmp = &Base2::val2;//Base2::* 型的变量
cout << bmp << endl;
printf(
"~~~~~~~~~~~~~~~~~~~%d\n",bmp);

func1(bmp,pd);
//这里必须由编译器内部转换
// func1(,pd);
}
int main()
{
Base1 base1;
base1.val1
= 1;
Base2 base2;
base2.val2
= 2;
Derived d;
Derived
*p = &d;
func2(p);
cout
<< "-------------------" << endl;
//以下结果都是0
printf("&Base1::val1 = %p\n",&Base1::val1);
printf(
"&Base2::val2 = %p\n",&Base2::val2);
printf(
"&Derived::val1 = %p\n",&Derived::val1);
printf(
"&Devrived::val2 = %p\n",&Derived::val2);

cout
<< &Base1::val1 << endl;
cout
<< &Base2::val2 << endl;
cout
<< &Derived::val1 << endl;
cout
<< &Derived::val2 << endl;

cout
<< "--------------" << endl;
printf(
"&Derived2::val1 = %p\n",&Derived2::val1);
printf(
"&Devrived2::val2 = %p\n",&Derived2::val2);
printf(
"&Derived2::val = %p\n", &Derived2::val3 );

cout
<< &Derived2::val1 << endl;
cout
<< &Derived2::val2 << endl;
cout
<< &Derived2::val3 << endl;
return 0;
}

  运行结果如下:GCC和VC下都是同样的结果

可以看出的是 在c++中cout 和printf 输出的结果竟然还是不一样的 == ,应该是 C++重载了 <<运算符,使<<能够适应各种输出的原因吧

 int Base2::* bmp = &Base2::val2;//Base2::* 型的变量
cout << bmp << endl;

通过 cout 可以看出这里输出的就是1,但是 在GCC下 不能转化为 int型的,所以才有了调用   func1(bmp,pd); 并在函数中 cout << pd->*dmp << endl; 时得到了 一个随机数 
对于C++对象模型中所说的 &Base1::val1 中val 指的是 val在类的对象中的偏移量问题,只能通过printf("&Base1::val1 = %p\n",&Base1::val1);看到,cout 方式可能还是因为重载的缘故吧:所有的输出都是1(不知道原因,可能不是偏移量了吧)
printf("&Devrived::val2 = %p\n",&Derived::val2); 对于&Derived::val2实际的偏移量应该是4,可能由于编译器的优化,输出为0了。。(怎么优化的? 想不明白)
 书中以   printf("&Derived2::val = %p\n", &Derived2::val3 ); 打印出了 val3的偏移量为8,可以看出

3. 那个point2d,3d问题
#include <iostream>
#include
<stdio.h>
using namespace std;
class Point3d
{
public:
virtual ~Point3d();
Point3d(
float a,float b,float c)
{
x
= a;
y
= b;
z
= c;
// origin(x,y,z);
}
static Point3d origin;
static void f()
{
//error: request for member 'x' in 'Point3d::origin',
//which is of non-class type 'Point3d()'
//printf("&origin.x = %p\n",&(origin.x));
//printf("&origin.y = %p\n",&origin.y);
//printf("&origin.z = %p\n",&origin.z);
// printf("&origin = %p\n",&origin);
}
float x,y,z;
};

int main()
{
float f = 1.0;
cout
<< sizeof(f) << endl;
cout
<< sizeof(float) << endl;
cout
<< sizeof(double) << endl;
printf(
"&Point3d::x = %p\n",&Point3d::x);//计算的是偏移量 4
printf("&Point3d::y = %p\n",&Point3d::y);//4 ,结果是8
printf("&Point3d::z = %p\n",&Point3d::z);//4 结果是C(12)

cout
<< "&Point3d::x = " << &Point3d::x << endl;
cout
<< "&Point3d::y = " << &Point3d::y << endl;
cout
<< "&Point3d::z = " << &Point3d::z << endl;
//undefined reference to `Point3d::origin'
// printf("&origin.x = %p\n",&(Point3d::origin.x));
// printf("&origin.y = %p\n",&Point3d::origin.y);
// printf("&origin.z = %p\n",&Point3d::origin.z);
Point3d p();

//Point3d::f();


return 0;
}
木有打印出来 origin.x ,错误是 
(1) //undefined reference to `Point3d::origin' ,
(2)//error: request for member 'x' in 'Point3d::origin',
        //which is of non-class type 'Point3d()'

virtual ~Point3d(); 去掉虚函数~,变为 Point3d()并完成初始化后:Point3d Point3d::origin(1,1,1);

#include <iostream>
#include
<stdio.h>
using namespace std;
class Point3d
{
public:
~Point3d(){};
Point3d(
float a,float b,float c)
{
x
= a;
y
= b;
z
= c;
}
static Point3d origin;

float x,y,z;
};
Point3d Point3d::origin(
1,1,1);
int main()
{
float f = 1.0;
cout
<< sizeof(f) << endl;
cout
<< sizeof(float) << endl;
cout
<< sizeof(double) << endl;
printf(
"&Point3d::x = %p\n",&Point3d::x);
printf(
"&Point3d::y = %p\n",&Point3d::y);
printf(
"&Point3d::z = %p\n",&Point3d::z);

cout
<< "&Point3d::x = " << &Point3d::x << endl;
cout
<< "&Point3d::y = " << &Point3d::y << endl;
cout
<< "&Point3d::z = " << &Point3d::z << endl;
//undefined reference to `Point3d::origin'
printf("&origin.x = %p\n",&(Point3d::origin.x));
printf(
"&origin.y = %p\n",&Point3d::origin.y);
printf(
"&origin.z = %p\n",&Point3d::origin.z);

//Point3d::f();


return 0;
}

  

结果如下:

对比与 两个图中的 &Point3d::x 值得出结论:

在GCC编译器中,如果加了 virtual ,它的对象布局中应该是 vptr在 数据成员的上面

而不是像 c++对象模型 cfont 编译器中在数据成员下面



  



抱歉!评论已关闭.