在C++中,通常的架构设计都是基于多态,基于接口编程。通常的是基类提供接口,子类根据具体的业务逻辑来实现接口,以此来提供程序设计的过程当中的可注入性,提升灵活性,可是事实可能不经如此。引入了多态,其实也就是引入了耦合,其强制规定了继承基类和接口的形式,这在总体继承体系中都是不能够更改的。ios
以下例子:编程
#ifndef ANIMAL_H #define ANIMAL_H #include <iostream> class Animal { public: virtual void eat() = 0; virtual ~Animal() = 0; }; Animal::~Animal() { } class Dog : public Animal { public: void eat() { std::cout << "DOG EAT MEAT!\n"; } ~Dog() {} }; class Cat : public Animal { public: void eat() { std::cout << "CAT EAT FISH!\n"; } ~Cat() {} }; class Pet { public: Pet(Animal *_a) : _aAnimal(_a) { }
~Pet()
{
delete _aAnimal;
} void eat() { _aAnimal->eat(); } private: Animal *_aAnimal; }; #endif // ANIMAL_H
Dog *dog = new Dog(); Pet p(dog); p.eat(); Cat *cat = new Cat(); Pet p1(cat); p1.eat();
C++0x中的bind函数和function模板类为咱们提供了很好的设计解决方案,提供多态基于函数对象,其只和函数的返回值和参数有关。陈硕老师称其为Object-base编程,经过对象来完成功能注入。拳拳到肉(陈老师原话)。关于bind和function不清楚的能够先了解下,这边就不赘述了。性能优化
看这个例子:架构
#include <iostream> #include <functional> #include <list> class Work { public: typedef std::function<void ()> doAmessage; void registerDoMessage(const doAmessage &f) { _aAmessage = f; } void do_aTask() { std::cout << "DO A TASK!\n"; } void aMessageComing() { _aAmessage(); } private: doAmessage _aAmessage; }; class Logic { public: typedef std::function<void ()> doTaskCallBack; Logic(const doTaskCallBack &f) : _dtask(f) { } void make() { _dtask(); } void aMessageComing() { _messageList.push_back("A TASK!"); } void printMessages() { for (auto ite = _messageList.begin(); ite != _messageList.end(); ++ite) { std::cout << (*ite).data() << '\n'; } } private: doTaskCallBack _dtask; std::list<std::string> _messageList; }; int main() { //std::cout << "Hello World\n"; Work worker; Logic logic(std::bind(&Work::do_aTask,worker)); worker.registerDoMessage(std::bind(&Logic::aMessageComing,&logic)); logic.make(); worker.aMessageComing(); worker.aMessageComing(); logic.printMessages(); return 0; }
Work::do_aTask为Logic提供服务,在Logic::make中调用,在
Logic logic(std::bind(&Work::do_aTask,worker)); 这句完成了注入操做。
Work::aMessageComing,须要Logic提供的具体的逻辑,在worker.registerDoMessage(std::bind(&Logic::aMessageComing,&logic));
完成了注入。
若是如今我定义了一个class,其只用提供一个void xxx()成员函数,那就能够直接绑定给Work使用。函数
能够注意到个人回调对象都是性能
std::function<void ()>
为何,我是想在提供一些变化。
好比,Logic的aMessageComing(Parameter *_p)函数添加了一个函数,我但愿Work不须要改变,这就须要一个参数,使用对象来实现对参数的保存。定义以下:struct Parameter { Parameter() : para1(0), para2(0) { } int para1; int para2; };使用以下:Parameter para; Work worker; Logic logic(std::bind(&Work::do_aTask,worker)); worker.registerDoMessage(std::bind(&Logic::aMessageComing,&logic,¶)); logic.make(); worker.aMessageComing(); para.para2 += 10; worker.aMessageComing(); logic.printMessages();运行结果:这样能够不改变Work,多引入一个参数,但是却也映入了一个全局的变量,在须要的使用须要改变参数,由于可能咱们不知道函数的调用时间,咱们须要作随时改变。
这样咱们就不须要经过继承完成注入,使用function和bind须要经过对象来完成注入。不使用继承虚函数使用函数对象能够得到运行时的效率,函数对象能够被inline,提供了性能优化。