转贴:http://hi.baidu.com/j2ee_cn/blog/item/3819f6bf88582d0e18d81f44.html

1.数据类型自身的对齐值:就是上面交代的基本数据类型的自身对齐值。
2.指定对齐值:#progma pack (value)时的指定对齐值value。
3.结构体或者类的自身对齐值:其成员中自身对齐值最大的那个值。
4.数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中小的那个值。
有了这些值,我们就可以很方便的来讨论具体数据结构的成员和其自身的对齐方式。有效对齐值N是最终用来决定数据存放地址方式的值,最重要。有效对齐N,就是表示“对齐在N上”,也就是说该数据的"存放起始地址%N=0".而数据结构中的数据变量都是按定义的先后顺序来排放的。第一个数据变量的起始地址就是数据结构的起始地址。结构体的成员变量要对齐排放,结构体本身也要根据自身的有效对齐值圆整(就是结构体成员变量占用总长度需要是对结构体有效对齐值的整数倍,结合下面例子理解)。这样就不能理解上面的几个例子的值了。
例子分析:
分析例子B;
struct B
{
char b;
int a;
short c;
};
假设B从地址空间0x0000开始排放。该例子中没有定义指定对齐值,在笔者环境下,该值默认为4。第一个成员变量b的自身对齐值是1,比指定或者默认指定对齐值4小,所以其有效对齐值为1,所以其存放地址0x0000符合0x0000%1=0.第二个成员变量a,其自身对齐值为4,所以有效对齐值也为4,所以只能存放在起始地址为0x0004到0x0007这四个连续的字节空间中,复核0x0004%4=0,且紧靠第一个变量。第三个变量c,自身对齐值为2,所以有效对齐值也是2,可以存放在0x0008到0x0009这两个字节空间中,符合0x0008%2=0。所以从0x0000到0x0009存放的都是B内容。再看数据结构B的自身对齐值为其变量中最大对齐值(这里是b)所以就是4,所以结构体的有效对齐值也是4。根据结构体圆整的要求,0x0009到0x0000=10字节,(10+2)%4=0。所以0x0000A到0x000B也为结构体B所占用。故B从0x0000到0x000B共有12个字节,sizeof(struct B)=12;
posted @ 2008-05-07 18:09 moonz-wu 阅读(570) 评论(0) 编辑

这个话题是源自于一个面试题,我在网上查了一下有不少这方面的解说!我自己整理了一下,选择了一个自认为是最优方案!
我们从最简单的开始:
首先,大家都知道要阻止类被实例化,可以通过使用private or protected 关键字来声明默认构造函数。那么在阻止类被继承的时候,我们需要用到这个技巧。其次,阻止类被继承还需要使用private来控制继承的基类。

namespace SamplePrivate
{

#ifdef NDEBUG

    
class Sealed
    
{
        
protected:
            Sealed() 
{};

            friend 
class SampleSealedClass; // 设置友类,以便访问Sealed的构造函数
    }
;

    
class SampleSealedClass : private virtual Sealed
    
{
    }
;

    
#else
    
class SampleSealedClass {}
#endif

}
这样我们就可以实例化SampleSealedClass,并且还不用担心被继承了。不过还是要解释一下为什么阻止了继承?
当我们写出下面的代码时,编译器在编译过程中做了什么呢?
class subclass : public SampleSealedClass
{
};
首先,当你在实例化subclass的时候,会先调用SampleSealedClass的构造函数,而在这之前会调用Sealed类的默认构造函数,但是我们发现Sealed是不能被实例化的,并且通过private virtual的继承只能被SampleSealedClass调用,因此这很好的阻止了类被继承。但是这里我们只能完成一个类被不被继承,那么是否有更好的方法来实现阻止任意类被继承呢?
那就需要用到模板了:
#ifdef NDEBUG

namespace SealedClasses
{
    
class Sealed
    
{
        
protected:
            Sealed() 
{}
    }
;

    template
<class T> class TypeWapper 
    
{
        
public:
            typedef T type;
    }
;
}


template
<typename T> class BaseSealed : private virtual SealedClasses::Sealed
{
    friend 
class SealedClasses::TypeWapper<T>::type; 
}
;

#else

template
<typename T> class BaseSealed
{
}
;


#endif
这里的TypeWapper主要是将外部类型传递到SealedClasses的,从而能得到访问Sealed构造函数的能力。不过这段代码在GCC4.0中通过编译,而在vs2008中不能通过。可以向下面这样来引用:
class subclass : BaseSealed<subclass>
{
    
public:
        subclass() 
{ cout << "subclass" << endl; }
}
;

// 下面这个会编译失败
class ssubclass : public subclass
{
    
public:
        ssubclass() 
{ cout << "ssubclass" << endl; }
}
;
posted @ 2008-05-07 11:52 moonz-wu 阅读(737) 评论(2) 编辑