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...相关推荐
- printf输出字符串_C语言入门必学第一课,学习“输入与输出”!
数据输入 编写程序的主要目的就是为了处理数据.数据从哪里来?数据的来源有很多种方式,如从磁盘文件中读取数据.从数据库中读取数据.从网页中抓取数据等,还有一种原始的方式就是从键盘输入数据. 在C语言中, ...
- c语言printf输出语句_C语言中另一个printf()语句中的printf()语句
c语言printf输出语句 A printf() function is a standard library function, that is used to print the text and ...
- C语言之printf输出中文乱码
C语言之printf输出中文乱码 不同编辑器问题解决方案 Clion编辑器 不同编辑器问题解决方案 根据不同的编辑器的表现进行针对性的处理. Clion编辑器 按照以下步骤操作编辑器设置即可: Fil ...
- Go语言fmt.Sprintf、fmt.Printf(格式化输出)
fmt.Printf fmt.Printf在程序中使用%f来格式化所需的值 看起来我们的值被四舍五入到了一个合理的数.但小数点后仍显示了6位,这对我们当前的需要来说实在是太多了. 对于这种情况,格式化 ...
- c语言printf输出带符号,输出字符串用什么符号-C语言怎么用printf输出字符串。
C语言怎么用printf输出字符串. void main() { unsigned char *x = "ab,sdf,sad,23432,cc"; data = x; print ...
- c语言用getchar函数输入两个字符c1,c语言:用getchar函数读入两个字符给c1,c2,用putchar和printf输出。思考问题...
用getchar函数读入两个字符给c1,c2,分别用putchar和printf输出这两个字符.思考以下问题: (1)变量c1和c2定义为字符型还是整型?或二者皆可? (2)要求输出c1和c2的ASC ...
- c语言printf输出多个字母,C语言printf嵌套printf然后再嵌套一个printf,嵌套printf输出的疑惑...
写一个程序,用程序来说明 郁金香Q吧 #include int main( void ) { int i = 1234; printf( "%d", printf( "% ...
- c语言对浮点数的处理默认是double吗,C语言中浮点数float和double输出的问题
C语言中浮点数float和double输出的问题 关注:260 答案:6 信息版本:手机版 解决时间 2019-01-12 07:33 斑駁影 2019-01-11 09:20 #includev ...
- C语言 va_start / va_end / va_arg 自定义 printf 函数 - C语言零基础入门教程
目录 一.前言 二.函数不定长参数简介 1.va_start 2.va_arg 3.va_end 三.win32 控制台版本 四.MFC 对话框版本 五.猜你喜欢 零基础 C/C++ 学习路线推荐 : ...
最新文章
- 简单DP【p2642】双子序列最大和
- 深入浅出 Redis client/server交互流程
- DCMTK:测试ConcatenationCreator类
- 存根类 测试代码 java_为旧版代码创建存根-测试技术6
- 少儿编程150讲轻松学Scratch(二)-制作过马路小游戏
- es6 Reflect对象的静态方法
- 【Elasticsearch】 es 排查问题 explain 使用 内容解释
- 踩过坑才懂:如何快速打造技术产品
- 使用NVivo完善定性编码的艺术
- 安装oracle所有依赖包,安装oracle11g R2 缺少依赖包
- matlab获取2的整数次幂,如何快速判断正整数是2的N次幂
- HiveSql计算占比、同比、占环比
- 辐射避难所ol修改服务器数据,辐射避难所ol12月17日数据互通公告
- python实现画板_一起看看python+pygame简单画板实现代码实例
- $.ajax()方法使用详解
- css做名单,css基础教程:2021年适合新手的7个CSS入门教程推荐
- jquery easyui iconcls(小图标)属性的设置
- windows远程桌面连接使用方法及技巧
- 支付系统核心架构设计思路(万能通用)
- golang实战-nsq集群入门与坑
热门文章
- JS中回调函数的写法
- Python数据库字段拆分数据
- python列表字典如何提取_怎么提取字典里面的列表里面的字典的value
- Linux驱动编程 step-by-step (七) 并发 竞态 (信号量与自旋锁)
- Ubuntu安装Sublime Text并输入中文
- Laravel 5.2问题-----postman进api的post请求,为什么出现Forbidden?
- Java刷题知识点之方法覆盖(方法重写)和方法重载的区别
- filter(HTML)滤镜用法
- 设计模式(2)策略模式 (模式讲解+应用)
- .NET定时任务执行管理器开源组件–FluentScheduler