时间:2016年9月11日 天气:小雨:umbrella:
Author:冬之晓:angry:
Email: 347916416@qq.com
MyAppearance: 
今天下了一天的雨,天气立刻就凉快了下来。记得刚来余姚的时候,感觉非常不 适应,天天都闷热,现在渐渐习惯了。今天早晨,和姥姥视频聊天,发现姥姥现在 说话越来越慢了,心里非常难受。真希望姥姥能好起来!
条款27:尽量少做转型动作
首先是C++提供的四种转型操作:
-
const_cast:常量性的转除。
-
dynamic_cast:安全的向derived class进行转型,可能会带来很高的开销
-
reinterpret_cast:低级转型,例如可讲pointer转成int,不建议使用
-
static_cast: 强迫隐式转换,例如int to const int,int to double, 但是const int 到 int 只有const_cast能做到。
在我们面前经常出现的一种使用情况是,像下面这样:
class Window{
public:
virtual void onResize(){...}
...
};
class SpecialWindow: public Window{
public:
virtual void onResize(){
static_cast<Window>(*this),onResize();
...
}
...
}
但是实际上上面的副本不能如愿以偿的调用其基类部分的onResize(),其事实上调用的是SpecialWindow的基类部分的副本的的单独的onResize,实际上和SpecialWindow的resize没有什么关系。这时,如果SpecialWindow本身也尝试去修改SpecialWidnow的非基类部分的话,那么对象就会进入一种伤残的状态.其基类部分没有进行必要的修改,但是派生类单独的部分却经历了修改,这样对象就会进入一种伤残的状态.
其实调用基类的Resize的正确方法根本就不需要用到转型操作:
class SpecialWindow:public Window{
public:
virtual void onResize(){
Window::onResize(){
.......
}
...
}
};
再论dynamic_cast,记住一般起调用带来的开销还是比较大的。而一般需要dynamic_cast的主要情况是,只拥有一个base class 指针的情况下,想要对derived class进行单独的处理。一般有两种方式可以替代dynamic_cast达到这种效果.
第一种方法是取一个容器并在里面存储,直接指向derived class对象的指针(往往是智能指针)。
typedef vector<shared_ptr<SpecialWindow>> VPSW;
VPSW windPtrs;
...
for(VPSW::iterator iter = windPtrs.begin();
iter != windPtrs.end(); ++iter){
iter->blink();
}
还有一种方法就是,将虚函数从derived class向上再延伸一层,这样,直接使用Base class 的指针,就可以调用derived class的函数。
记住,优秀的代码是很少使用转型操作的,应该尽可能的隔离转型操作。
请记住:
-
如果可以,尽量避免转型,特别是在注重效率的代码中避免dynamic_casts。如果有个设计需要转型动作,试着发展无需转型的替代设计。
-
如果转型是必要的,试着将它隐藏于某个函数背后。客户随后可以调用该函数,而不需将转型放进他们自己的代码内。
-
宁可使用C++风格的新式转型,少用C风格转型,因为前者很容易辨识出来,而且也比较有着分门别类的职掌。
设计模式(十三)————观察者模式
观察者模式,也叫做发步-订阅模式:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,
这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己 举一个公司工作的例子,例子中秘书和boss充当观察者,通知员工们开始工作的更新!
#ifndef OBSERVER
#define OBSERVER
#include <QtDebug>
#include <QString>
#include <QSharedPointer>
#include "subject.h"
class Observer
{
public:
// Observer(){}
Observer(QString name, Subject *sub):_name(name),_sub(QSharedPointer<Subject>(sub)){}
virtual ~Observer(){}
virtual void update()=0;
protected:
QString _name;
QSharedPointer<Subject> _sub;
};
class StockObserver final:public Observer
{
public:
StockObserver(QString name, Subject *sub):Observer(name, sub){}
void update() override
{
qDebug() <<_sub->getSubjectState()<<_name<<"关掉股票,开始工作!";
}
};
class AnimationObserver final:public Observer
{
public:
AnimationObserver(QString name, Subject *sub):Observer(name, sub){}
void update() override
{
qDebug() <<_sub->getSubjectState()<<_name<<"关掉动漫,开始工作!";
}
};
#endif // OBSERVER
#ifndef SUBJECT
#define SUBJECT
#include <QtDebug>
#include <QString>
#include <QList>
class Observer;
class Subject
{
public:
// Subject(){}
virtual ~Subject()
{
#if 1
qDeleteAll(_observers);
#else
for(auto i:_observers)
{
delete i;
}
#endif
_observers.clear();
}
virtual void Attach(Observer *observer) = 0;
virtual void Detch(Observer *observer) = 0;
virtual void Notify() = 0;
// void setSubjectState(QString str){_action = str;}
QString getSubjectState(){return _action;}
protected:
QString _action;
QList<Observer *> _observers;
};
class Boss:public Subject
{
public:
Boss(){Subject::_action = QString::fromUtf8("I am boss!");}
void Attach(Observer *observer) override
{
_observers.append(observer);
}
void Detch(Observer *observer) override
{
_observers.removeOne(observer);
delete observer;
observer = nullptr;
}
void Notify() override; //override不能写在类外面!!
};
class Secretary:public Subject
{
public:
Secretary(){Subject::_action = QString("I am secretary!");} //子类为啥不能初始化父类的成员变量
void Attach(Observer *observer) override
{
_observers.append(observer);
}
void Detch(Observer *observer) override
{
_observers.removeOne(observer);
delete observer;
observer = nullptr;
}
void Notify() override; //override不能写在类外面!!
};
#endif // SUBJECT
#include "subject.h"
#include "observer.h"
void Boss::Notify()
{
for( auto i:_observers)
{
i->update();
}
}
void Secretary::Notify()
{
for( auto i:_observers)
{
i->update();
}
}
#include "observer.h"
#include "subject.h"
int main(int argc, char * argv[])
{
Subject *st = new Secretary();
Observer *a = new StockObserver("妈妈",st);
Observer *b = new AnimationObserver("小东",st);
st->Attach(a);
st->Attach(b);
st->Detch(b);
st->Notify();
return 0;
}
这个例子通过观察者员工们的状态,同时在构造观察者的时候可以设置观察者的状态,达到了观察者模式的效果。