C++中结构体和类

      本博文是在阅读android源码的过程中,发现代码中有类继承结构体的情况,之前很少见,就在这里总结一下,加深一下印象。本博文只是本人学习笔记记录所得,如果博文中有什么问题,请大家指出来,大家一起学习。

1.C++中的结构体

       C++中的结构体和类基本上没什么区别了,基本上可以把它当做类来使用,在下面这个实验例程验证了C++结构体和类很多共通性质:包括多态,虚指针,继承,内存分布。所以看到类继承于某个结构体也不要奇怪了。例程,我在本地编译验证过,伙计们可以亲自下刀试试。

1)源代码

 

#include<iostream>
using namespace std;
struct test1{
        int pub;  //C++结构体默认属性是public,在后面main函数中可直接访问
    public:
        int a;
        int b;
        test1(){  //也可以有构造函数。
            cout <<"test1"<<endl;
        }
        int fun1(int,int);
        int fun2(int,int);
        virtual int fun3(int,int); //也可以有虚函数
    private:
        int aa; //private 真的是私有吗
};
int test1::fun1(int a,int b){
    cout<<"hello shanghai\n"<<endl;
    return 0;
}
int test1::fun2(int a,int b){
    cout<<"hello beijing \n"<<endl;
    return 0;
}
int test1::fun3(int a,int b){
    cout<<"hello shenzhen\n"<<endl;
    return 0;
}

struct test2:test1{ //test2继承于test1,它的内存分布和test1有什么区别吗
    test2(){
        cout<<"test2"<<endl;    
    }  
    int c; 
    int d;
    int fun3(int a,int b){
        cout<<"hello hangzhou\n"<<endl;
        return 0;
    }
};

int main(){
    test1 t1;
    test2 t2;
    t2.a =5;
    test1 *t3 = new test1();
    t3 = new test2();
    t3->fun3(3,3); //这里会打出hello hangzhou字样,多态体现出来了吧。<strong></strong>
    //t2.aa = 55;//error: ‘int test1::aa’ is private 直接调用声明为private的变量,编译器也是会报错的。
    cout<<"t2.a:"<<t2.a<<endl;
    t2.fun1(1,2);
    t2.fun2(3,4);
    t2.fun3(5,6);
    cout<<"sizeof t2.pub:"<<sizeof(t2.pub)<<endl;  //这里直接访问了pub域,说明成员属性默认是public
    cout<<"sizeof test1:"<<sizeof(struct test1)<<endl;
    cout<<"sizeof test2:"<<sizeof(struct test2)<<endl;
    cout<<"sizeof t2.pub:"<<sizeof(t2.c)<<endl;
}

打印结果:

 

test1
test1
test2
test1
test1
test2
hello hangzhou

t2.a:5
hello shanghai

hello beijing

hello hangzhou

sizeof t2.pub:4
sizeof test1:24
sizeof test2:32
sizeof t2.pub:4

2)打印结果发现

1.开始处交替打出了test1,test2类的构造函数名字,说明在每次定义一个对象时都会调用相应的构造函数,这个性质和类是一致的。

2.定义的是父类指针,而new的是子类对象,由于存在虚函数,就打印出子类的hangzhou字样。

3.在打印大小的时候,我特意打出test1域pub大小,一来可以验证C++类默认属性是public,而来可以看看编译器安排test1中int对齐大小,这里看是4字节。同样test2类也是将int4字节对齐。针对test1类对象大小,4个int型数据域加上一个虚函数表指针就是24个,即4*4+8=24.同理test2对象多出8个字节的数据域,所以大小是32个字节。

4.C++结构体,如果声明的有虚函数,那么同样存在虚表,而且在内存分布上,依然会安排在类实例的首地址。

3) C++结构体也有虚表:

可以发现虚表和类的没有任何区别。

 

Vtable for test1
test1::_ZTV5test1: 3u entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI5test1)
16    test1::fun3

Class test1
   size=24 align=8
   base size=24 base align=8
test1 (0x7f4610929850) 0
    vptr=((& test1::_ZTV5test1) + 16u) 

Vtable for test2
test2::_ZTV5test2: 3u entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI5test2)
16    test2::fun3

Class test2
   size=32 align=8
   base size=32 base align=8
test2 (0x7f461096d1c0) 0
    vptr=((& test2::_ZTV5test2) + 16u) 
  test1 (0x7f461096d230) 0
      primary-for test2 (0x7f461096d1c0)

 

2.C语言中结构体

1)c的结构体当中不允许有函数存在(有函数指针很正常吧),所以c的结构体就没有了构造函数,析构函数,虚函数等。

2)c的结构体成员变量的访问权限只能是public。

3)c的结构体不允许继承的,编译起来会报错的。

3.C++中类继承结构体

       在写下面这个例子的时候遇到了点麻烦,本来一开始我想把普通的静态函数hehe1,hehe2,与类写在同一个命名空间,但是写在同一命令空间,在类构造函数中给fun1和fun2赋值的时候,总是遇到错误,因此就分成两个命名空间,这时类test实例内存开始处存放的就是这两个函数指针的值。这样的用法,在android framework用法不少,大家多百度百度,理解深入一点。

 

#include<iostream>

using namespace std;
namespace arm{

typedef struct test1{
    void (*fun1)(void);
    void (*fun2)(void);
}callback_t;

extern "C" {
static void hehe1(void){
    cout<<"hehe1"<<endl;
}
static void hehe2(void){
    cout<<"hehe2"<<endl;
}
}
}

namespace TI{
class test:public arm::callback_t
{
    public:
        test(){
            this->fun1 = arm::hehe1;
            this->fun2 = arm::hehe2;
        }
        ~test(){}
};
}

int main(){
	TI::test *t1 = new TI::test();
	(t1->fun1)();
	(t1->fun2)();
        cout<<"hehe1:"<<(void*)arm::hehe1<<endl;
        cout<<"hehe2:"<<(void*)arm::hehe2<<endl;
        return 0;
}

打印结果:

 

hehe1
hehe2
hehe1:0x4008f2
hehe2:0x400914
调试结果
(gdb) p t1->fun1
$1 = (void (*)(void)) 0x4008f2 <arm::hehe1()>
(gdb) p t1->fun2
$2 = (void (*)(void)) 0x400914 <arm::hehe2()>
(gdb) p hehe1
$3 = {<text variable, no debug info>} 0x4008f2 <arm::hehe1()>
(gdb) p hehe2
$4 = {<text variable, no debug info>} 0x400914 <arm::hehe2()>
(gdb) p *t1
$5 = {<arm::just> = {fun1 = 0x4008f2 <arm::hehe1()>, fun2 = 0x400914 <arm::hehe2()>}, <No data fields>}
上面打印结果和我们调试结果是一致的,C++发现结构体和类基本没什么区别吧。
 

3.C++类和结构体区别

1)C++类的内部成员变量和成员函数访问级别可有public,protected,private三种,默认情况下是private。而C++结构体内部成员变量和成员方法默认的访问级别是public。

2)C++类的继承默认是private,而结构体的继承默认是public。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值