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

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

2011-08-31 13:41 351 查看
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);//计算的是偏移量 4printf("&Point3d::y = %p\n",&Point3d::y);//4  ,结果是8printf("&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 编译器中在数据成员下面
  

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: