分享
 
 
 

女娲造人----构造析构与对象的生死

王朝other·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

女娲造人

----构造析构与对象的生死

作者:HolyFire

在《由始至终----构造与析构》最后我提到了C++中的构造函数和析构函数与对象的生和死有着很大的关系,好好运用还能控制对象的生死,使得编程的思路更接近现实世界的规律。

我们先回忆一下,在对象创建的时候,合适的构造函数将被自动调用,而对象销毁的时候,析构函数将被自动调用。在构造函数与析构函数可以被随意调用的情况下,也就是被声明为public的时候,这没有任何问题,但是一旦我们将他们的可视性改为private与protected呢,那么情况就有所改观了。

声明为private的时候,那么除了类本身可以调用外,还有用friend关键字赋予信任关系的对象(一般是类或者函数)可以访问。

#include <iostream>

using namespace std;

class A{

public:

static A * CreateA( void )

{

cout << "Create a A instance By class A's Member Function" << endl;

return new A;

}

private:

A(){ }

friend A * CreateA( void );

};

A * CreateA( void )

{

cout << "Create a A instance By class A's friend Function" << endl;

return new A;

}

void main()

{

A * a1 = A::CreateA();

A * a2 = CreateA();

delete a1;

delete a2;

cin.get();

}

结果是:

Create a A instance By class A's Member Function

Create a A instance By class A's friend Function

如果你直接用A a这样的方式,是无法创建A的实例的,编译器会告诉你,它帮不上忙。

当然,将析构函数声明为私有也可以限制将A的实例销毁的条件,那么

delete a1;

delete a2;

也会遭到编译器的抗议,我们需要另外写一个函数或者类来销毁他们。

在现实生活中有很多事物是有限的。比如说太阳系中只有一个太阳,如果有两个太阳会出什么乱子呢,真的是难以想象。在创建的对象有条件限制的时候,我们可以写文档告诉别人在编程的时候注意,但是随着工程的日益庞大,不要说别人,连自己也有可能忘记,在对条件限制要求非常严格的情况下,我们的知识便派上了用场。

结合刚才讲的将构造函数声明为私有的内容和《独一无二----静态成员变量》的内容,我们可以设计一个只能有一个实例的类型。下面是C++的源代码,这个例子中,对实例的销毁也加上了限制。

#include <iostream>

using namespace std;

class A{

private:

static A * a; //一个静态成员变量,类的所有实例所共有的

A(){ cout << "This is class A , I couldn't direct Creat instance" << endl; }

~A(){ cout << "This is Class A , I coudn't direct Destroy instance" << endl; }

public:

void ShowInstance(){ cout << this << endl; }

friend A * CreatObjectOfA( void ); //委托信任关系,由于类没有提供创建实例的方法,那么这个任务就交给了这个函数了。

friend void DestroyObjectOfA( A * a ); //对应创建,这个函数负责销毁产生的实例

};

A* A::a = NULL;

A * CreatObjectOfA( void )

{

if( A::a == NULL ) //之前有没有创建过A的实例

{//没有

A::a = new A;

cout << "This is a Class A Instance Creat By CreatObjectOfA Function ." << endl;

}//创建过的话就不用再创建了

return A::a; //由于A::a是静态成员变量,那么返回的都是同一个指针

}

void DestroyObjectOfA( A * _a )

{

if( A::a != NULL )//对应创建,如果现在有实例被创建过,那么销毁它

{

delete A::a;

A::a = NULL;

cout << "This is a Class A Instance Destroy By DestroyObjectOfA Function ." << endl;

}

_a = NULL;

}

void main()

{

A * a1 , * a2 , * a3;

a1 = CreatObjectOfA();

a2 = CreatObjectOfA();

a3 = CreatObjectOfA();

a1->ShowInstance();

a2->ShowInstance();

a3->ShowInstance();

DestroyObjectOfA( a1 );

DestroyObjectOfA( a2 );

DestroyObjectOfA( a3 );

cin.get();

}

结果是:

This is class A , I couldn't direct Creat instance

This is a Class A Instance Creat By CreatObjectOfA Function .

00864898 //指向的都是同一个地方

00864898

00864898

This is Class A , I coudn't direct Destroy instance

This is a Class A Instance Destroy By DestroyObjectOfA Function .

至始至终只有一个实例被创建和销毁了

无论你创建多少次,这个类的实例最多有一个,这正是我们想要的。只要你肯去想,有很多有趣的事物在等着你。

将构造函数与析构函数声明为protected(保护),那么我们的目的就是这个类将作为基类,而且这个基类不能直接实例化。为什么要这样做,事实上我们在理解事物和对大量事物进行抽象的时候,会有一些不完整的片断,他们单独的出现是不合适的。比如说一些简单加工后的半成品,甚至是现实中找不到例子的,他们的语义是残缺不全的。也有完全抽象化的,比如说:“人”,不具体到男人,女人,小孩,大人,就无法用现实的思想来考虑它。

那么就用一个C++的例子来实现一下,从而掌握它。

#include <iostream>

using namespace std;

class A{

protected:

A(){ cout << "This is class A , I couldn't direct Creat instance" << endl;}

};

class B : public A{

public:

B(){ cout << "This is class B public inherit From class A , I could Creat instance By class B" << endl; }

};

void main()

{

B b;

cin.get();

}

结果是:

This is class A , I couldn't direct Creat instance

This is class B public inherit From class A , I could Creat instance By class B

这个例子很简单,我们不需要花多少时间就能理解。

到现在才回到标题上来似乎有些突然,但是没有上面的解释,理解起来会有些困难,那么废话少说,我们直接切入主题。

中国古老的传说中,人是女娲用泥巴做的,所以说,人不能随意创建,可以创建人的事物可以是女娲。

女娲变出了男人和女人,女人可以生孩子,也就是可以创建人,但是只有男人才能让女人生孩子,所以关系是,要创建人必须要有一个男人来让一个女人生孩子,生孩子的行为是女人的,但是主动权也就是男人才有权利使用女人的行为,这是男人的行为。我们可以理解为男人的行为是发一条消息来告诉女人,女人采用相应的行为来处理。

我们来整理一下:(我使用一种简化的模式来考虑问题,要点在于理清构造函数对于对象生死的关系)

男人和女人都是人,女人可是生孩子,孩子也是人,所以孩子要分成男人和女人,那么女人生孩子事实上是两种行为,生男孩,生女孩,男人也有两种行为,让女人生男孩,让女人生女孩。

女娲{ 创造男人,创造女人 }

人{}

男人{ 人 ,让女人生男孩(男人) ,让女人生女孩(女人)}

女人{ 人 ,生男孩(男人),生女孩(女人)}

class Person{ //人

protected:

Person(){} //构造函数可以让派生类使用,也就是男人和女人使用

};

class Man;

class Woman;

class NvWa{ //女娲

public:

Man * CreatAMan(void); //创造男人

Woman * CreatAWoman( void ); //创造女人

};

class Woman : virtual public Person{ //女人

private:

Woman(){}

Man * CreatAMan( void ); //生男孩(男人)

Woman * CreatAWoman( void ); //生女孩(女人)

friend NvWa;

friend Man;

};

class Man:virtual public Person{ //男人

private:

Man(){}

public:

Man * GetABoy( Woman * woman ) //让女人生男孩(男人)

{

return woman->CreatAMan();

}

Woman * GetAGirl( Woman * woman ) //让女人生女孩(女人)

{

return woman->CreatAWoman();

}

friend NvWa;

friend Woman;

};

Man * NvWa::CreatAMan( void )

{

return new Man;

}

Woman * NvWa::CreatAWoman( void )

{

return new Woman;

}

Man * Woman::CreatAMan( void )

{

return new Man;

}

Woman * Woman::CreatAWoman( void )

{

return new Woman;

}

void main()

{

NvWa nvwa; //女娲

Man * man = nvwa.CreatAMan(); //创造了一个男人

Woman * woman = nvwa.CreatAWoman(); //创造了一个女人

Man * boy = man->GetABoy( woman ); //男人让女人生了一个男孩

Woman * girl = man->GetAGirl( woman ); //又让女人生了一个女孩

delete man;

delete woman;

delete boy;

delete girl;

}

其实细心的朋友不难发现,创建人可以抽象成一个行为,男人和女人都是人,但是这样做不知道生下来的是男孩或是女孩,因为继承的特性不能由其基类来得知派生类的信息,这个问题在C++中也有解决的办法,我会在以后的文章中介绍。

2001/9/18

丁宁

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有