帐前卒专栏

code, software architect, articles and novels.
代码,软件架构,博客和小说

转载自http://blog.csdn.net/logic_nut/archive/2009/10/22/4711489.aspx

推荐看看:http://www.math.ucla.edu/~tom/

学习理论在这里:http://www.math.ucla.edu/~tom/Game_Theory/Contents.html

博弈问题
若你想仔细学习博弈论,我强烈推荐加利福尼亚大学的Thomas S.
Ferguson教授精心撰写并免费提供的这份教材,它使我受益太多。(如果你的英文水平不足以阅读它,我只能说,恐怕你还没到需要看“博弈论”的时 候。)

Nim游戏是博弈论中最经典的模型(之一?),它又有着十分简单的规则和无比优美的结论,由这个游戏开始了解博弈论恐怕是最合适不过了。

Nim游戏是组合游戏(Combinatorial Games)的一种,准确来说,属于“Impartial Combinatorial
Games”(以下简称ICG)。满足以下条件的游戏是ICG(可能不太严谨):1、有两名选手;2、两名选手交替对游戏进行移动(move),每次一
步,选手可以在(一般而言)有限的合法移动集合中任选一种进行移动;3、对于游戏的任何一种可能的局面,合法的移动集合只取决于这个局面本身,不取决于轮
到哪名选手操作、以前的任何操作、骰子的点数或者其它什么因素;
4、如果轮到某名选手移动,且这个局面的合法的移动集合为空(也就是说此时无法进行移动),则这名选手负。根据这个定义,很多日常的游戏并非ICG。例如
象棋就不满足条件3,因为红方只能移动红子,黑方只能移动黑子,合法的移动集合取决于轮到哪名选手操作。

通常的Nim游戏的定义是这样的:有若干堆石子,每堆石子的数量都是有限的,合法的移动是“选择一堆石子并拿走若干颗(不能不拿)”,如果轮到某个人时所
有的石子堆都已经被拿空了,则判负(因为他此刻没有任何合法的移动)。

这游戏看上去有点复杂,先从简单情况开始研究吧。如果轮到你的时候,只剩下一堆石子,那么此时的必胜策略肯定是把这堆石子全部拿完一颗也不给对手剩,然后
对手就输了。如果剩下两堆不相等的石子,必胜策略是通过取多的一堆的石子将两堆石子变得相等,以后如果对手在某一堆里拿若干颗,你就可以在另一堆中拿同样
多的颗数,直至胜利。如果你面对的是两堆相等的石子,那么此时你是没有任何必胜策略的,反而对手可以遵循上面的策略保证必胜。如果是三堆石子……好像已经
很难分析了,看来我们必须要借助一些其它好用的(最好是程式化的)分析方法了,或者说,我们最好能够设计出一种在有必胜策略时就能找到必胜策略的算法。

定义P-position和N-position,其中P代表Previous,N代表Next。直观的说,上一次move的人有必胜策略的局面是P-
position,也就是“后手可保证必胜”或者“先手必败”,现在轮到move的人有必胜策略的局面是N-position,也就是“先手可保证必
胜”。更严谨的定义是:1.无法进行任何移动的局面(也就是terminal position)是P-position;2.可以移动到P-
position的局面是N-position;3.所有移动都导致N-position 的局面是P-position。

按照这个定义,如果局面不可能重现,或者说positions的集合可以进行拓扑排序,那么每个position或者是P-position或者是N-
position,而且可以通过定义计算出来。

以Nim游戏为例来进行一下计算。比如说我刚才说当只有两堆石子且两堆石子数量相等时后手有必胜策略,也就是这是一个P-position,下面我们依靠
定义证明一下(3,3)是一个P-position。首先(3,3)的子局面(也就是通过合法移动可以导致的局面)有(0,3)(1,3)(2,3)(显
然交换石子堆的位置不影响其性质,所以把(x,y)和(y,x)看成同一种局面),只需要计算出这三种局面的性质就可以了。
(0,3)的子局面有(0,0)、(0,1)、(0,2),其中(0,0)显然是P-position,所以(0,3)是N-position(只要找到 一个是P-
position的子局面就能说明是N-position)。(1,3)的后继中(1,1)是P-position(因为(1,1)的唯一子局 面(0,1)是N-
position),所以(1,3)也是N-position。同样可以证明(2,3)是N-position。所以(3,3)的所有 子局面都是N-
position,它就是P-position。通过一点简单的数学归纳,可以严格的证明“有两堆石子时的局面是P-position当且
仅当这两堆石子的数目相等”。

根据上面这个过程,可以得到一个递归的算法——对于当前的局面,递归计算它的所有子局面的性质,如果存在某个子局面是P-position,那么向这个子
局面的移动就是必胜策略。当然,可能你已经敏锐地看出有大量的重叠子问题,所以可以用DP或者记忆化搜索的方法以提高效率。但问题是,利用这个算法,对于
某个Nim游戏的局面(a1,a2,…,an)来说,要想判断它的性质以及找出必胜策略,需要计算O(a1a2…*an)个局面的性质,不管
怎样记忆化都无法降低这个时间复杂度。所以我们需要更高效的判断Nim游戏的局面的性质的方法。

直接说结论好了。(Bouton’s Theorem)对于一个Nim游戏的局面(a1,a2,…,an),它是P-
position当且仅当a1a2an=0,其中表示异
或(xor)运算。怎么样,是不是很神奇?我看到它的时候也觉得很神奇,完全没有道理的和异或运算扯上了关系。但这个定理的证明却也不复杂,基本上就是按
照两种position的证明来的。

根据定义,证明一种判断position的性质的方法的正确性,只需证明三个命题: 1、这个判断将所有terminal position判为P-
position;2、根据这个判断被判为N-position的局面一定可以移动到某个P-position;3、根据这个判 断被判为P-
position的局面无法移动到某个P-position。

第一个命题显然,terminal position只有一个,就是全0,异或仍然是0。

第二个命题,对于某个局面(a1,a2,…,an),若a1a2…^an!=0,一定存在某个合法的移动,将ai改变成ai’后满足
a1a2ai’an=0。不妨设a1a2an=k,则一定存在某个ai,它的二进制表示在k的最高位上是1(否则k的
最高位那个1是怎么得到的)。这时aik<ai一定成立。则我们可以将ai改变成ai’=aik,此时
a1a2ai’an=a1a2an^k=0。

第三个命题,对于某个局面(a1,a2,…,an),若a1a2…^an=0,一定不存在某个合法的移动,将ai改变成ai’后满足
a1a2ai’an=0。因为异或运算满足消去率,由a1a2an=a1a2ai’…^an可以得
到ai=ai’。所以将ai改变成ai’不是一个合法的移动。证毕。

根据这个定理,我们可以在O(n)的时间内判断一个Nim的局面的性质,且如果它是N-position,也可以在O(n)的时间内找到所有的必胜策略。
Nim问题就这样基本上完美的解决了。

在下一节“Sprague-Grundy函数”中,我们将面对更多与Nim游戏有关的变种,还会看到Nim游戏的a1a2…^an这个值更广泛的
意义。敬请期待。
上一期的文章里我们仔细研究了Nim游戏,并且了解了找出必胜策略的方法。但如果把Nim的规则略加改变,你还能很快找出必胜策略吗?比如说:有n堆石
子,每次可以从第1堆石子里取1颗、2颗或3颗,可以从第2堆石子里取奇数颗,可以从第3堆及以后石子里取任意颗……这时看上去问题复杂了很多,但相信你
如果掌握了本节的内容,类似的千变万化的问题都是不成问题的。

现在我们来研究一个看上去似乎更为一般的游戏:给定一个有向无环图和一个起始顶点上的一枚棋子,两名选手交替的将这枚棋子沿有向边进行移动,无法移动者判
负。事实上,这个游戏可以认为是所有Impartial Combinatorial
Games的抽象模型。也就是说,任何一个ICG都可以通过把每个局面看成一个顶点,对每个局面和它的子局面连一条有向边来抽象成这个“有向图游戏”。下
面我们就在有向无环图的顶点上定义Sprague-Garundy函数。

首先定义mex(minimal excludant)运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非负整数。例如mex{0,1,2,4}=3、
mex{2,3,5}=0、mex{}=0。

对于一个给定的有向无环图,定义关于图的每个顶点的Sprague-Garundy函数g如下:g(x)=mex{ g(y) | y是x的后继 }。

来看一下SG函数的性质。首先,所有的terminal
position所对应的顶点,也就是没有出边的顶点,其SG值为0,因为它的后继集合是空集。然后对于一个g(x)=0的顶点x,它的所有后继y都满足
g(y)!=0。对于一个g(x)!=0的顶点,必定存在一个后继y满足g(y)=0。

以上这三句话表明,顶点x所代表的postion是P-position当且仅当g(x)=0(跟P-positioin/N-position的定义的
那三句话是完全对应的)。我们通过计算有向无环图的每个顶点的SG值,就可以对每种局面找到必胜策略了。但SG函数的用途远没有这样简单。如果将有向图游
戏变复杂一点,比如说,有向图上并不是只有一枚棋子,而是有n枚棋子,每次可以任选一颗进行移动,这时,怎样找到必胜策略呢?

让我们再来考虑一下顶点的SG值的意义。当g(x)=k时,表明对于任意一个0<=i<k,都存在x的一个后继y满足g(y)=i。也就是
说,当某枚棋子的SG值是k时,我们可以把它变成0、变成1、……、变成k-1,但绝对不能保持k不变。不知道你能不能根据这个联想到Nim游戏,Nim
游戏的规则就是:每次选择一堆数量为k的石子,可以把它变成0、变成1、……、变成k-1,但绝对不能保持k不变。这表明,如果将n枚棋子所在的顶点的
SG值看作n堆相应数量的石子,那么这个Nim游戏的每个必胜策略都对应于原来这n枚棋子的必胜策略!

对于n个棋子,设它们对应的顶点的SG值分别为(a1,a2,…,an),再设局面(a1,a2,…,an)时的Nim游戏的一种必胜策略是把
ai变成k,那么原游戏的一种必胜策略就是把第i枚棋子移动到一个SG值为k的顶点。这听上去有点过于神奇——怎么绕了一圈又回到Nim游戏上了。

其实我们还是只要证明这种多棋子的有向图游戏的局面是P-position当且仅当所有棋子所在的位置的SG函数的异或为0。这个证明与上节的 Bouton’s
Theorem几乎是完全相同的,只需要适当的改几个名词就行了。

刚才,我为了使问题看上去更容易一些,认为n枚棋子是在一个有向图上移动。但如果不是在一个有向图上,而是每个棋子在一个有向图上,每次可以任选一个棋子
(也就是任选一个有向图)进行移动,这样也不会给结论带来任何变化。

所以我们可以定义有向图游戏的和(Sum of Graph
Games):设G1、G2、……、Gn是n个有向图游戏,定义游戏G是G1、G2、……、Gn的和(Sum),游戏G的移动规则是:任选一个子游戏Gi
并移动上面的棋子。Sprague-Grundy
Theorem就是:g(G)=g(G1)g(G2)…^g(Gn)。也就是说,游戏的和的SG函数值是它的所有子游戏的SG函数值的异或。

再考虑在本文一开头的一句话:任何一个ICG都可以抽象成一个有向图游戏。所以“SG函数”和“游戏的和”的概念就不是局限于有向图游戏。我们给每个
ICG的每个position定义SG值,也可以定义n个ICG的和。所以说当我们面对由n个游戏组合成的一个游戏时,只需对于每个游戏找出求它的每个局
面的SG值的方法,就可以把这些SG值全部看成Nim的石子堆,然后依照找Nim的必胜策略的方法来找这个游戏的必胜策略了!

回到本文开头的问题。有n堆石子,每次可以从第1堆石子里取1颗、2颗或3颗,可以从第2堆石子里取奇数颗,可以从第3堆及以后石子里取任意颗……我们可
以把它看作3个子游戏,第1个子游戏只有一堆石子,每次可以取1、2、3颗,很容易看出x颗石子的局面的SG值是x%4。第2个子游戏也是只有一堆石子,
每次可以取奇数颗,经过简单的画图可以知道这个游戏有x颗石子时的SG值是x%2。第3个游戏有n-2堆石子,就是一个Nim游戏。对于原游戏的每个局
面,把三个子游戏的SG值异或一下就得到了整个游戏的SG值,然后就可以根据这个SG值判断是否有必胜策略以及做出决策了。其实看作3个子游戏还是保守了
些,干脆看作n个子游戏,其中第1、2个子游戏如上所述,第3个及以后的子游戏都是“1堆石子,每次取几颗都可以”,称为“任取石子游戏”,这个超简单的
游戏有x颗石子的SG值显然就是x。其实,n堆石子的Nim游戏本身不就是n个“任取石子游戏”的和吗?

所以,对于我们来说,SG函数与“游戏的和”的概念不是让我们去组合、制造稀奇古怪的游戏,而是把遇到的看上去有些复杂的游戏试图分成若干个子游戏,对于
每个比原游戏简化很多的子游戏找出它的SG函数,然后全部异或起来就得到了原游戏的SG函数,就可以解决原游戏了。
例子程序:
acm.hdu上的例子

A New Tetris Game 22222

#include
#include
#include
#include
//#include
using namespace std;

//better if find area that not linked and sg each
typedef bitset<32> int_set;
struct array2{
bitset<64> bs;
int r,c;
bool operator<(const array2& a2)const{
if(r!=a2.r)return r<a2.r;
if(c!=a2.c)return c<a2.c;
return (long long)&bs< (long long)&a2.bs;
}
bitset<64>::reference operator()(int ir,int ic){
return bs[ir*c+ic];
}
}g;
inline int mex(const int_set& is){
if(is.none())return 0;
for(int i=0;i!=32;++i){ //assum i will never exceed 32
if(is.test(i)==0)
return i;
}
}
inline bool check_ok(int ir,int ic){
return !g(ir,ic)&&!g(ir+1,ic)&&!g(ir,ic+1)&&!g(ir+1,ic+1);
}
map<array2,int> ma;
inline void set_it(int ir,int ic,int s){
g(ir,ic)=s;
g(ir+1,ic)=s;
g(ir,ic+1)=s;
g(ir+1,ic+1)=s;
}
inline int sg(int r,int c){
map<array2,int>::iterator p=ma.find(g);//optimizing for the repeated
if(p!=ma.end())return p->second;
int_set sgs;
for(int i=0;i<r-1;++i)
for(int j=0;j<c-1;++j)
if(check_ok(i,j)){
set_it(i,j,1);
sgs.set(sg(r,c));
set_it(i,j,0);
}
return ma[g]=mex(sgs);
}
int main(){
int n;
while(cin>>n){
int out=0;
while(n–){
int r,c;
cin>>g.r >>g.c;
for(int i=0;i!=g.r;++i)
for(int j=0;j!=g.c;++j){
char c;
cin>>c;
g(i,j)=c-‘0’;
}
out^=sg(g.r,g.c);
}
cout<<(out?“Yes”:“No”)<<endl;
}
return 0;
}

node1 node2
nothing

xml 格式如上.

首先要得到root节点:

from xml.etree.ElementTree import ElementTree tree = ElementTree()
tree.parse(filename) # 你想使用哪个文件作为输入? root = tree.getroot()
“”“如果你的输入的是一段content”“” from xml.etree.ElementTree import XML file =
open(filename) content = file.read(-1) root = XML(content) print(root.tag)
file.close() # or you can use from xml.etree.ElementTree import XMLID file =
open(filename) root = XMLID(file.read(-1)) print(root[0].tag) # root[0] is
file.close()

上面的root是class Element的object, 而tree 是ElementTree的object. 如果想得到某个节点的attribute,
例如
则element.attrib[‘name’]即可.如果是text,就是element.text.

如果想得到下一层节点,可以使用root.find(tag)得到,如果不知道具体的tag,那么可以使用root.getchildren().如果想使用某个ta
g作为迭代,例如nodes中有两个node.代码如下:

element_nodes = root.find(‘nodes’) nodes_list =
element_nodes.getiterator(‘node’) for node in nodes_list: print(node.tag)

copy from http://www.cnitblog.com/ictfly/archive/2006/11/25/19594.html

本文只是本人对C++中关于静态类型的一个总结,如错误之处,请大家帮我改正。我分两个方面来总结,第一方面主要是相对于面向过程而言,即在这方面不涉及
到类,第二方面相对于面向对象而言,主要说明static在类中的作用。

一、在面向过程设计中的static关键字

1、 静态全局变量

定义:在全局变量前,加上关键字 static 该变量就被定义成为了一个静态全局变量。

特点:
A、该变量在全局数据区分配内存。
B、初始化:如果不显式初始化,那么将被隐式初始化为0。
C、访变量只在本源文件可见, 严格的讲应该为定义之处开始到本文件结束。

例(摘于C++程序设计教程—钱能主编P103):         //file1.cpp
#include<iostream.h>
void fn();
extern int n;
void main()
{
n=20;
cout << n << endl;
fn();
}

//file2.cpp
#include<iostream.h>

static int n; //定义静态全局变量,初始化为0;
void fn()
{
n++;
cout << n << endl;
}

文件 分别编译能通过,但连接时file1.cpp 中的变量n找不到定义,产生连接错误。

D、文件作用域下声明的const的常量默认 为static存储类型。

2、静态局部变量

定义:在局部变量前加上static关键字时,就定义了静态局部变量。

特 点:
A、该变量在全局数据区分配内存。
B、初始化:如果不显式初始化,那么将被隐式初始化为0。
C、它始终驻 留在全局数据区,直到程序运行结束。但其作用域为局部作用域,当定义它的函数或 语句块结束时,其作用域随之结束。

3、静态函数(注意 与类的静态成员函数区别)

定义:在函数的返回类型前加上static关键字,函数即被定义成静态函数。

特点:
A、静态函数只能在本源文件中使用(这是与普通函数区别)
例(摘于C++程序设计教程—钱能主编P103):         //file1.cpp
void fn();
void staticFn()

void main()
{

fn();
staticFn();
}

//file2.cpp
#include<iostream.h>

static void staticFn();
void fn();

void fn()
{
staticFn();
cout << “this is fn() /n”;
}

void staticFn()
{
cout << “this is staticFn() /n”;
}
连接时,将产生找不到函数 staticFn()定义的错误。

B、主意事项

在文件作用域下声明的inline函数默认为static类 型。

二、面象对象中的static关键字(主要指类中的static关键字)

1、静态数据成员

特 点:
A、内存分配:在程序的全局数据区分配。
B、初始化和定义:
a、静态数据成员定义时要分配空间,所以不 能在类声明中定义。
b、为了避免在多个使用该类的源文件中,对其重复定义,所在,不能在类的头文件中
定义。
c、静态数据成员因为程序一开始运行就必需存在,所以其初始化的最佳位置在类的内部实现。
C、特点
a、对相于 public,protected,private 关键字的影响它和普通数据成员一样,
b、因为其空间在全局数据区分配,属于所有本类
的对象共享,所以,它不属于特定的类对象,在没产生类对象时其作用域就可见,即在没有产生类的实例时,我们就可以操作它。

D、访问 形式
a、 类对象名.静态数据成员名
b、 类类型名:: 静态数据成员名

E、静态数据成员,主要 用在类的所有实例都拥有的属性上。比如,对于一个存款类,帐号相对
于每个实例都是不同的,但每个实例的利息是相同的。所以,应该把利息设为存款类的
静态数据成员。这有两个好处,第一,不管定义多少个存款类对象,利息数据成员都共享分配在全局区的内存,所以节省存贮空间。第二,一旦利息需要改变时,只
要改变一次,则所有存款类对象的利息全改变过来了,因为它们实际上是共用一个东西。

2、静态成员函数

特点:
A、静态成员函数与类相联系,不与类的对象相联系。
B、静态成员函数不能访问非静态数据成员。原因很简单,非静态数据成员属于特定的类实 例。

作用:
主要用于对静态数据成员的操作。
调用形式:
A、类对象名.静态成员函数名()
B、类类型名:: 静态成员函数名()

copy from http://www.javaperformancetuning.com/news/qotm030.shtml

What does

1
volatile
do?

This is probably best explained by comparing the effects that

1
volatile
and
1
synchronized
have on a method.
1
volatile
is a field modifier, while
1
synchronized
modifies code blocks and methods. So we can specify three variations of a simple accessor using those two keywords:

1
2
3
         int i1;              int geti1() {return i1;}
volatile int i2; int geti2() {return i2;}
int i3; synchronized int geti3() {return i3;}
1
geti1()
accesses the value currently stored in
1
i1
in the current thread. Threads can have local copies of variables, and the data does not have to be the same as the data held in other threads. In particular, another thread may have updated
1
i1
in it's thread, but the value in the current thread could be different from that updated value. In fact Java has the idea of a "main" memory, and this is the memory that holds the current "correct" value for variables. Threads can have their own copy of data for variables, and the thread copy can be different from the "main" memory. So in fact, it is possible for the "main" memory to have a value of 1 for
1
i1
, for thread1 to have a value of 2 for
1
i1
and for thread2 to have a value of 3 for
1
i1
if thread1 and thread2 have both updated
1
i1
but those updated value has not yet been propagated to "main" memory or other threads.

On the other hand,

1
geti2()
effectively accesses the value of
1
i2
from “main” memory. A
1
volatile
variable is not allowed to have a local copy of a variable that is different from the value currently held in “main” memory. Effectively, a variable declared
1
volatile
must have it’s data synchronized across all threads, so that whenever you access or update the variable in any thread, all other threads immediately see the same value. Of course, it is likely that
1
volatile
variables have a higher access and update overhead than “plain” variables, since the reason threads can have their own copy of data is for better efficiency.

Well if

1
volatile
already synchronizes data across threads, what is
1
synchronized
for? Well there are two differences. Firstly
1
synchronized
obtains and releases locks on monitors which can force only one thread at a time to execute a code block, if both threads use the same monitor (effectively the same object lock). That’s the fairly well known aspect to
1
synchronized
. But
1
synchronized
also synchronizes memory. In fact
1
synchronized
synchronizes the whole of thread memory with “main” memory. So executing
1
geti3()
does the following:

  1. The thread acquires the lock on the monitor for object
    1
    this
    (assuming the monitor is unlocked, otherwise the thread waits until the monitor is unlocked).
  2. The thread memory flushes all its variables, i.e. it has all of its variables effectively read from "main" memory (JVMs can use dirty sets to optimize this so that only "dirty" variables are flushed, but conceptually this is the same. See section 17.9 of the Java language specification).
  3. The code block is executed (in this case setting the return value to the current value of
    1
    i3
    , which may have just been reset from "main" memory).
  4. (Any changes to variables would normally now be written out to "main" memory, but for
    1
    geti3()
    we have no changes.)
  5. The thread releases the lock on the monitor for object
    1
    this
    .
So where
1
volatile
only synchronizes the value of one variable between thread memory and "main" memory,
1
synchronized
synchronizes the value of all variables between thread memory and "main" memory, and locks and releases a monitor to boot. Clearly
1
synchronized
is likely to have more overhead than
1
volatile
.

貌似网上大家都使用Easytalk搭建微博系统。那东东使用php和mysql的。就是备案难了点,可以考虑放到米国。小量用户速度蛮快的,大量的用户没有测试过.
…(废话ing)有个家伙做了一个IT的微博,就是贴代码麻烦了点,要先去http://pastebin.com那里发布成功,然后再从分享那里贴进来。。。虽然
webservice已经大行其道,但是真正的接口互用似乎还要等到在未来的若干年。

I use c++ in linux which is gcc version 4.4.1 (Ubuntu 4.4.1-4ubuntu9).

I considered that c++ memory alignment is like the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// pseudo-code of memory alignment
remove_all_static_varibles();
int max= 0;
foreach(element in struct)
find_the_max_memory_used(element,&amp;max);
int align = max &gt; default? default: max;
// if max memory used for element is larger than the default, use default.
int memory = sum(memory_used(elements));

if(memory%align != 0)
// here will execute alignment!
{
memory = (memory/align + 1 )*align;
}
if(memory == 0)
memory = 1;
return memory;

vc++ use #pragma_pack(n) set the default.if there are three char in a struct, like:

1
2
3
4
5
6
typedef struct{
char a;
char b;
char c;
}X;
sizeof(X); // it will be 3
1
2
3
4
5
6
7
8
9
10
11
12
13
typedef struct{
char a;
short b;

}Y;
sizeof(Y); // here will be 4

typedef struct{
char a;
int b;
}Z;

sizeof(Z); // here will be 8
1
2
3
4
5
6
7
8
typedef struct{
double a;
char b;
}W;
sizeof(W);
// it will be 12, the align is 4
// when the max memory used is larger
// than 4, it will be 4

if the class or struct is empty, sizeof(it) will be 1.

But if there are static varibles in classes or structs, you can remove it!. like:

1
2
3
4
5
class A{
static int a;

};
sizeof(A); // it will be 1

in class there will be many class functions. But A class is thought as A struct and many functions set. sizeof(A class) will compute the size of struct.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class ZZ{
public:
ZZ(){
int a = 3;
cout &lt;&lt; "I am ZZ"&lt;&lt;endl;
cout &lt;&lt; a&lt;&lt;endl;
}
~ZZ(){

}
int c;
};
sizeof(ZZ); // will be 4;
/* it is like a struct and two member functions.
struct ZZ{
int c;
};

ZZ@ZZ() is name mingling
ZZ@ZZ(){
int a = 3;
cout &lt;&lt; "I am ZZ"&lt;&lt;endl;
cout &lt;&lt; a&lt;&lt;endl;
}
ZZ@~ZZ(){

}
*/

but when we meet the virtual member functions and virtual derived class, it will be different.

又拆了个本本,这个本本设计的不怎么合理。安装的时候严丝合缝,拆卸的时候就相当的麻烦。首先拧掉所有看得见的螺丝。先拆电源板,要先将屏转到180度,拆掉电源,然
后再拆电源板。拆下电源板时,再拧掉键盘的螺丝和外壳螺丝。这里键盘的螺丝滑了…我就没有继续拆卸…zzz

近期看一个电影<二维平面>(FlatLand),这个电影讲述的是二维平面中发生的故事.发现任何事物都很难脱离自身所在的环境想问题.二维中的square
A就是这样.他只知东西南北四个方向,完全没有向上和向下的概念.所以圆球说线移动成面,面移动成体,对square A来说完全没有概念.但是当square A脱
离了他原本所在的二维平面,他人也就大彻大悟了.如果有一维直线,也就有二维平面,如果有二维平面,也就会有三维立体空间,如果有三维立体空间,也就会存在四维世界.
在二维世界中如果有人宣扬或者知道三维世界,就要被杀掉,因为不利于二维世界的统治.毕竟如果知道还有更高级的生命体或者个体存在,现在的体制就会土崩瓦解.并非出于
惧怕,而是出于信仰.就如同如果神真的存在,那么人还有什么值得崇拜和推崇的?电光火石中争长短,几许光阴;蜗牛角上较雌雄,许大世界?不过真的有四维世界吗?这首先
要论证真的有二维世界和一维世界吗?因为在我们的世界中暂时还找不到二维物体.想多了就晕,即使知道了事实也无法证明.即使证明了也会引来杀身之祸.所以无知是福.觉
得非常奇怪的一点就是知道了就去宣扬,这让我想到日心说.想来哥白尼的确是位智者.当然逼哥白尼临终发表天体运行论的那群人也很聪明.相反布鲁诺多多少少有些愚钝.不
过提点别人的错误,往往自己也抱持相同的错误.最后用白居不易的<对酒>一诗结束此文:蜗牛角上争何事,石火光中寄此身,随贫随福且欢乐,不开口笑是痴人.

** 中 文名 ** : 二维电影

** 英文名 ** : Flatland

** 别名 ** : Flatland the Film

** IMDb ** : 7.0/10 (455 votes)

** 资 源格式 ** : DVDRip

** 发行日期 ** : 2007年

** 导 演 ** : Ladd Ehlinger Jr.

** 演员 ** : Chris Carter … King Of Lineland
Megan Colleen … A Hexagon

Ladd Ehlinger Jr. … A Square

Oscar Gutierrez … Old Trapezoid

Simon Hammond … A Sphere

Michael Karle … Pentagon Doctor

Jeff Sanders … Cube Carlton

Jonathon Shoemaker … Soldier X

Gregory Trent … President Circle

** 地区 ** : 美国

** 语 言 ** : 英语

** 简 介 ** :

[ ](http://image-1.verycd.com/3eb62b5e6eb5aba3cd79530a50037c2845609/post-32595
9-1221031016.jpg)

◎译  名  二维电影
◎片  名 Flatland
◎年  代 2007
◎国  家 美国
◎类  别 动画/奇幻/科幻
◎ 语  言 英语
◎字  幕 N/A
◎IMDB评分 7.4/10 (253 votes)
◎IMDB链接 http://www.imdb.com/title/tt0972374

◎文件格式 XviD + MP3
◎视频尺寸 656 x 272
◎文件大小 1CD 49 x 15MB
◎片  长 99 Mins
◎导  演  Ladd Ehlinger Jr.
◎主  演 Chris Carter … King Of Lineland
Megan Colleen … A Hexagon
Ladd Ehlinger Jr. … A Square
Oscar Gutierrez … Old Trapezoid
Simon Hammond … A Sphere
Michael Karle … Pentagon Doctor
Jeff Sanders … Cube Carlton
Jonathon Shoemaker … Soldier X
Gregory Trent … President Circle

◎简  介

Flatland: The Movie是由1884年一位英国牧师Edwin A.
Abbott(1838-1926)所撰写的一本小册子《Flatland》改编的一部动画片。小说里构造了一个全新的世界──这个世界是二维的!整个小
说分成两个部分,前一部分系统地描述这个二维世界,包括自然状况、居民生活、政治历史等等。真正有趣的事情发生在后一部分里,这里不同维度的世界之间发生
了碰撞——二维世界中的主人公拜访了一维世界,同时又接触到了一个全新的三维世界。当他在他的世界传播三维思想时,整个世界大乱,哥白尼时代的那段故事再 次发生。

1
2
3
#!/bin/sh
plink -ssh -D 7070 -P 22 -pw "$1" [email protected]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include&lt;cstdio&gt;

using namespace std;
namespace pattern{
/// this pattern links all handler as a line, if previous handler can process a request, it wil not be
/// send to next handler. For example, if someone requested changing programming style,
/// this decision will be made by a programmer.
/// He will change his programming style without noticing his lead.
/// But if someone request changing the requirements, the programmer can not make this decision.
/// He will noticing his lead, and make his lead decided.

/// this is request class.
#define STYLE 0
#define REQIREMENT 1
class Request{
public:
int type; // changing programming style or changing requirements?

};

/// this class for processing request.
class Handler{
private:
Handler* parent;
public:
Handler(Handler* p):parent(p){}
virtual bool DoHandle(Request&amp; r)=0;
void Process(Request&amp; r);
virtual ~Handler(){}
};

void Handler::Process(Request&amp; r){
if(!this-&gt;DoHandle(r) &amp;&amp; NULL != parent){
parent-&gt;Process(r);
}
}

class Programmer: public Handler{
public:
Programmer(Handler* p):Handler(p){}
virtual bool DoHandle(Request&amp; r);

};
bool Programmer::DoHandle(Request&amp; r){
if(r.type == STYLE){
printf("programmer: I can process changing programming style\n");
return true;
}else{
printf("programmer: I can not process this request. I will report this to my lead!\n");
return false;
}

}

class Lead:public Handler{
public:
Lead(Handler* p):Handler(p){}
virtual bool DoHandle(Request&amp; r);

};
bool Lead::DoHandle(Request&amp; r){
if(r.type == REQIREMENT){
printf("lead: I will process changing reqirements\n");
return true;
}
return false;
}
}

int main(){
pattern::Lead lead((pattern::Handler*)NULL);
pattern::Programmer programmer(&amp;lead);
pattern::Request r;
r.type = STYLE;
programmer.Process(r);
r.type = REQIREMENT;
programmer.Process(r);
return 0;

}
0%