c++编程风格----读书笔记(1)
来源:互联网 发布:淘宝卖家怎么品牌授权 编辑:程序博客网 时间:2024/05/17 23:36
一、抽象
在软件开发中,抽象处于一种中心地位,而类则是C++中最重要的抽象机制。类描述的是所有从这个类实例化出来的对象的共同属性,并且刻画了这些对象的共同行为。在C++设计中,正确识别抽象是一个很关键的步骤。如果想获得高质量的抽象,那么程序员就必须要充分地理解程序中的各种对象的内在属性。
1、编程风格示例,如下程序:
#include "stdafx.h"#include "iostream"enum CARD{ CDROM, TAPE, NEWWORK };enum MONITOR{ MONO, COLOR };class Card{public:virtual int Price() = 0;virtual char *Name() = 0;virtual int Rebate();};class NetWork : public Card{public:int Price();char *Name();};class CDRom : public Card{public:int Price();char *Name();int Rebate();};class Tape : public Card{public:int Price();char *Name();};class Monitor{public:virtual int Price() = 0;virtual char *Name() = 0;};class Color : public Monitor{public:int Price();char *Name();};class Monochrome : public Monitor{public:int Price();char *Name();};int Card::Rebate() { return 45; }int NetWork::Price() { return 600; }char *NetWork::Name() { return "NetWork"; }int CDRom::Price() { return 1500; }char *CDRom::Name() { return "CDRom"; }int CDRom::Rebate() { return 135; }int Tape::Price() { return 1000; }char *Tape::Name() { return "Tape"; }int Color::Price() { return 1500; }char *Color::Name() { return "Color"; }int Monochrome::Price() { return 500; }char *Monochrome::Name() { return "Mono"; }class Computer{public:Computer(CARD, MONITOR);~Computer();public:int NetPrice();void Print();private:Card*card;Monitor *mon;};Computer::Computer(CARD c, MONITOR m){switch (c){case CDROM:card = new CDRom();break;case TAPE:card = new Tape();break;case NEWWORK:card = new NetWork();break;default:break;}switch (m){case MONO:mon = new Monochrome();break;case COLOR:mon = new Color();break;default:break;}}Computer::~Computer(){if (card){delete card;card = NULL;}if (mon){delete mon;mon = NULL;}}int Computer::NetPrice(){return mon->Price() + card->Price() - card->Rebate();}void Computer::Print(){std::cout << card->Name() << " " << mon->Name() << " , " << "net Price = " << NetPrice() << std::endl;}int _tmain(int argc, _TCHAR* argv[]){Computer mn(NEWWORK, MONO);Computer mc(CDROM, MONO);Computer mt(TAPE, MONO);Computer cn(NEWWORK, COLOR);Computer cc(CDROM, COLOR);Computer ct(TAPE, COLOR);mn.Print();mc.Print();mt.Print();cn.Print();cc.Print();ct.Print();return 0;}
想一想这里是否有必要写得这么冗长和复杂?这个程序是不是一定需要8个类,并且其中有7个类含有虚函数,才能解决问题?
2、找出上面程序中共同的抽象
Card和Monitor这两个类的接口是相似的:它们都含有纯虚函数Pirce()和Name()。不同的地方在于Card类中海油一个虚函数Rebate()。所以可以把这两个类再次抽象出来一个Component类,还有这段代码:
int Computer::NetPrice(){return mon->Price() + card->Price() - card->Rebate();}
不应该显示地依赖于组件是否存在折扣,而应该对每种组件进行统一处理,这里实际上隐含了另一个抽象,如果将NetPrice也作为一个成员函数添加到Component类中,那么在函数Component::NetPrice()中只需调用Component的其他成员函数即可(也就是将共同的抽象提取出来并放到基类中)
3、来看看其他的如CDRom和NetWork之间的区别,而他们只在于各自虚函数返回的值时不同。在实际工作中,程序并不会为每个需要创建的对象提供一个不同的类,而是用一个类来表示一组对象(也就是一个类应该能够描述一组对象)
4、最初编写这个程序的人员陷入了一个常见的思维陷阱,他认为,在用C++来进行程序设计时,继承和虚函数是唯一的方法。于是,他在程序中过度地使用了继承,从而导致某些类的声明过于具体,甚至只能描述一种对象。如果在不同的对象之间有不同的行为,那么继承和多态是很有用的工具。然而,在本程序中,对象之间的不同之处在于他们的属性,而并非行为(如果派生类之间的区别在于属性,则用数据成员来表示;如果在于行为,则用虚函数来表示)
5、引入继承
经过修改,我们现在的程序只有Component,但是程序需要将扩展卡和显示器区分开来,并且他们只是折扣不一样,所以加入继承,为两者提供不同的构造函数,从而提供合适的特化
通常,如果派生类是基类的特化,存在着派生类是“一种基类对象”这种关系时,可以考虑将派生类之间的不同之处局限在初始化过程中
6、去掉枚举
Card和Monitor是两种截然不同的类型。如果将Computer::Computer的参数改为指向对象的指针,那么就可以去掉枚举和switch语句。
7、来看看经过修改的程序:
#include "stdafx.h"#include "iostream"class Component{public:Component(int price, char *name, int rebate):price_(price), name_(name), rebate_(rebate){}public:int Price() { return price_; }char *Name() { return name_; }int Rebate() { return rebate_;}int NetPrice(){ return (rebate_ - rebate_); }private:int price_;char *name_;int rebate_;};class Card : public Component{public:Card(int price, char *name, int rebate = 45): Component(price, name, rebate){}};class Monitor : public Component{public:Monitor(int price, char *name, int rebate = 0): Component(price, name, rebate){}};class Computer{public:Computer(Card *card, Monitor *monitor);public:int NetPrice();void Print();private:Card*card_;Monitor *monitor_;};Computer::Computer(Card *card, Monitor *monitor){card_ = card;monitor_ = monitor;}int Computer::NetPrice(){return (card_->Rebate() + monitor_->Rebate());}void Computer::Print(){std::cout << card_->Name() << " " << monitor_->Name() << " , " << "net price = " << NetPrice() << std::endl;}void InitSoming(){Card NetWork(600, "NetWork");Card CDRom(600, "CDROM", 135);Card Tape(600, "TAPE");Monitor Color(1500, "Color");Monitor Mono(500, "Mono");Computer mn(&NetWork,&Mono);Computer mc(&CDRom, &Mono);Computer mt(&Tape, &Mono);Computer cn(&NetWork,&Color);Computer cc(&CDRom, &Color);Computer ct(&Tape, &Color);mn.Print();mc.Print();mt.Print();cn.Print();cc.Print();ct.Print();}int _tmain(int argc, _TCHAR* argv[]){InitSoming();return 0;}
- c++编程风格----读书笔记(1)
- Essential c++,泛型编程风格读书笔记
- c++编程风格----读书笔记(2)
- 《C专家编程》读书笔记1
- C专家编程 读书笔记1
- C,C++基础和编程风格(1)
- C语言编程风格
- C编程风格
- C语言编程风格
- c语言编程风格
- c/c++编程风格
- C/C++编程风格
- C++/C编程风格规范
- 读书笔记 |Google C++编程风格指南
- c语言的编程风格
- c语言的编程风格
- c语言的编程风格
- c语言的编程风格
- 自己利用jQuery框架写的一个Table类!
- C++输出二进制、十进制、八进制和十六进制总结
- OData v3与WCF Data Services 5.x简介
- 【Visual C++】游戏开发笔记四十 浅墨DirectX教程之八 绘制真实质感的三维世界:光照与材质专场
- codeforces round 160(完全)
- c++编程风格----读书笔记(1)
- codeforces 70D 动态凸包
- c++编程风格----读书笔记(2)
- MATLAB 3D 动画制作(二)- 3D 动画动作设计
- MATLAB 3D 动画制作(三)- 实时随动3D动画设计
- VC编写的程序不能在其他机器上运行的解决方案(续)
- JavaScript的表达式解析器-1.引言
- 黑马程序员 07 Servlet 学习笔记 01
- 黑马程序员 08 Servlet 学习笔记 02 生命周期与servletCofig