1. 区别
默认的成员,继承修饰,struct为public,class为private。
2. 类和结构体的拷贝,赋值,在不涉及成员指针情况下可直接使用默认方式即可。
3. 构造函数调用时机:Struct s; 拷贝构造时机:Struct s = other; 赋值函数时机:Sturct s; s = other;
默认情况下不会相互调用,注意重载时勿要遗漏成员数据。
4. virtual 的应用
一、在继承方面:
B B B
| | / \
C D F G
\ / \ /
E H
①没有使用virtual ②使用了virtual
继承关系:
②的情况:F和G在虚拟继承之后结构上增加了一个指针的大小。H保留一份B的数据。
测试2:访问
测试3:多态
网上查到的资料说要对B的析构进行virtual修饰,修改之后的析构顺序为:
二、成员函数方面:一般指多态的实现
有个需要注意的方面是不要漏掉virtual对析构函数的修饰。
5. 内存对齐,这是编译器相关的
默认情况下不会相互调用,注意重载时勿要遗漏成员数据。
4. virtual 的应用
一、在继承方面:
B B B
| | / \
C D F G
\ / \ /
E H
①没有使用virtual ②使用了virtual
继承关系:
struct B
{
int ba;
int bb;
int bc;
~B()
{
printf("~B\n");
}
};
struct C : B
{
int ca;
~C()
{
printf("~C\n");
}
};
struct D : B
{
int da;
~D()
{
printf("~D\n");
}
};
struct E : C, D
{
~E()
{
printf("~E\n");
}
};
struct F : virtual B
{
int fa;
~F()
{
printf("~F\n");
}
};
struct G : virtual B
{
int ga;
~G()
{
printf("~G\n");
}
};
struct H : F, G
{
~H()
{
printf("~H\n");
}
};
测试1:数据结构
printf("B%d C%d D%d E%d\n", sizeof(B), sizeof(C), sizeof(D), sizeof(E));
printf("B%d F%d G%d H%d\n", sizeof(B), sizeof(F), sizeof(G), sizeof(H));
// out
// B12 C16 D16 E32
// B12 F20 G20 H28
①的情况:E会保存两份B的数据,一个来自C,一个来自D。②的情况:F和G在虚拟继承之后结构上增加了一个指针的大小。H保留一份B的数据。
测试2:访问
E e1;
/* e1.ba;
error: request for member `ba' is ambiguous
candidates are: int B::ba
int B::ba
*/
H h1;
h1.ba; // pass
①的情况:E对B的成员访问会出现二义性。②没有二义性。测试3:多态
//B* pb1 = new E; //error: `B' is an ambiguous base of `E'
B* pb2 = new H;
delete pb2; //*** glibc detected *** free(): invalid pointer: 0x08212018 ***
① 似乎不行。②编译通过了,可是出了问题。网上查到的资料说要对B的析构进行virtual修饰,修改之后的析构顺序为:
virtual ~B()
// ~H
// ~G
// ~F
// ~B
// B16 C20 D20 E40
// B16 F24 G24 H32
二、成员函数方面:一般指多态的实现
有个需要注意的方面是不要漏掉virtual对析构函数的修饰。
struct I
{
~I()
{
printf("~I\n");
}
};
struct J : I
{
~J()
{
printf("~J\n");
}
};
struct K
{
virtual ~K()
{
printf("~K\n");
}
};
struct L : K
{
~L()
{
printf("~L\n");
}
};
测试1:析构
I* pi = new J;
delete pi;
K* pk = new L;
delete pk;
// out:
// ~I
// ~L
// ~K
J的析构没有被调用。
5. 内存对齐,这是编译器相关的
struct N
{
int a;
double b;
float c;
};
struct O
{
int a;
float c;
double b;
};
printf("N%d O%d\n", sizeof(N), sizeof(O));
// out in linux gcc v3.4.4
// N16 O16
// out in windows vs2008
// N24 O16