C语言哆啦a梦用printf输出,【2013.1.20】故事的最后,哆啦A梦终于又回到了大雄身边。从此两个人过上了…——ProtoType...
// // // // // // // //?//
///2013.1.20
// // // // // // //?//?//
還記得小的時候看哆啦A夢,
里面有一話講到大雄用一個神奇的工具,
好像是一個燈之類的東西,
照一照點心,
點心就會自動復制到無限多(2^n)。
先不管這是不是一件讓人羨慕的事情,
但是這個道具,無意間實現了我們今天所要講的模式——Prototype。
【核心】使用復制(Clone)代替創建(new)對象。
UML圖表示:
從表面上看,
與其說是一個模式,
倒不如說是一種復制行為更為貼切。
然而,
這其中,卻隱藏著另一個難以察覺的問題。
它涉及到了對象拷貝的兩種方式:
——深拷貝與淺拷貝。
在探討這個兩種拷貝方式的區別之前,
首先要提到&這個運算符:
一般情況下,
它的使用方法與指針類似(但不是相等),
&a表示的是a的引用。
一個最簡單的使用方法如下所示:
void changeValue(const int& a)
{
a +=10;
}
int value = 10;
changeValue(value);
printf("%d",value);//輸出結果為20
一般函數傳遞的話,
并不可以直接修改實參的值,
然而我們可以利用傳遞實參的引用(即其地址)來做到這一點。
那么&這個運算符與Prototype有有什么關系呢?
其實,
在C++中,
即使是我們自定義的類,
也存在著一個看不到的復制構造函數,
它的寫法格式如下:
SomeClass(constSomeClass& C)
正因為存在著這個函數,
我們才能夠使用如下的方法進行對象之間的直接賦值創建:
SomeClass a;
SomeClass b(a);
這是非常方便的。
但是,
很遺憾,
默認的復制構造函數只是淺拷貝,
不是深拷貝。
二者大致的區別就是:
淺拷貝如果遇到動態變量(例如A類中聚合B類對象),就不能正確工作了,因為它只是將地址的引用傳給了另一個對象,并沒有另外開辟一段內存。
深拷貝就是從這方面著想,對內存實實在在地進行了第二份拷貝(而不是耍小聰明只是傳個引用)。
具體深拷貝與淺拷貝的區別可以看這篇文章:http://blog.csdn.net/bluescorpio/article/details/4322682
因此,
我們實現ProtoType的時候,
最值得注意的地方就是要創建適用于自己類的復制構造函數,
而不僅僅只是使用C++默認的那個。
具體代碼實例:
【大致思路】
虛基類Dessert類的兩個派生類分別使用了深克隆與淺克隆的方法,可以在他們同樣調用copyDessert之后輸出的結果中看出來這兩種克隆方法的差異。
Dessert.h
#ifndef _DESSERT_H_
#define _DESSERT_H_
class Dessert
{
public:
Dessert(){}
~Dessert(){}
virtual Dessert* copyDessert() = 0;
virtual void outputNum() = 0;
};
class DessertWithDepCopy:public Dessert
{
public:
DessertWithDepCopy();
DessertWithDepCopy(const DessertWithDepCopy& con);
~DessertWithDepCopy();
static int dessertNum;
Dessert* copyDessert();
void outputNum();
};
//Didn't define the copy constructor(Use default).
class DessertWithShallowCopy:public Dessert
{
public:
DessertWithShallowCopy();
~DessertWithShallowCopy();
static int dessertNum;
Dessert* copyDessert();
void outputNum();
};
#endif
Dessert.cpp
#include "Dessert.h"
#include
int DessertWithDepCopy::dessertNum = 0;
int DessertWithShallowCopy::dessertNum = 0;
//DeepCopy class's defination.
DessertWithDepCopy::DessertWithDepCopy()
{
dessertNum++;
}
DessertWithDepCopy::DessertWithDepCopy(const DessertWithDepCopy& con)
{
dessertNum++;
}
DessertWithDepCopy::~DessertWithDepCopy()
{
if(--dessertNum < 0)
dessertNum = 0;
}
Dessert* DessertWithDepCopy::copyDessert()
{
return new DessertWithDepCopy(*this);
}
void DessertWithDepCopy::outputNum()
{
std::cout<
}
//ShallowCopy class's defination.
DessertWithShallowCopy::DessertWithShallowCopy()
{
dessertNum++;
}
DessertWithShallowCopy::~DessertWithShallowCopy()
{
if(--dessertNum < 0)
dessertNum = 0;
}
Dessert* DessertWithShallowCopy::copyDessert()
{
return new DessertWithShallowCopy(*this);
}
void DessertWithShallowCopy::outputNum()
{
std::cout<
}
main.cpp
#include"Dessert.h"
#include
enum
{
Deep,
Shallow
};
int main()
{
Dessert* dessert[2];
dessert[Deep] = new DessertWithDepCopy();
dessert[Shallow] = new DessertWithShallowCopy();
std::cout<
dessert[Deep]->outputNum();
dessert[Shallow]->outputNum();
Dessert* newDessert[2];
//Copy construtor.
newDessert[Deep] = dessert[Deep]->copyDessert();
newDessert[Shallow] = dessert[Shallow]->copyDessert();
std::cout<
dessert[Deep]->outputNum();
dessert[Shallow]->outputNum();
return 0;
}
輸出結果:
【注意事項】
如上圖所示,在調用copyDessert方法之后,淺克隆的數量卻沒有增加,但這與我們程序的原有設想是相違背的。
因此,在自己編寫的類中,要記得對復制構造函數進行override,從而降低Bug發生概率。
總結
以上是生活随笔為你收集整理的C语言哆啦a梦用printf输出,【2013.1.20】故事的最后,哆啦A梦终于又回到了大雄身边。从此两个人过上了…——ProtoType...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 夜刀神索凉宫忧乄直播间(夜刀神索凉宫忧乄
- 下一篇: santa cruz biotechno