很显然我的对话框是一个点击接收者。它接受来自控件的点击:
class MyCtrl : public MyCtrlBase,至于控件方面:
public Clickreceiver
{
public:
virtual void OnClick();
private:
MyDlgCtrl *m_parentDlg;
MyCtrl * m_myCtrl;
}
class MyCtrl : public MyCtrlBase控件没有再依赖复杂的对话框类。而是依赖了一个接口。符合前面的推论2.
{
public:
virtual void OnClick();
private:
ClickReceiver *m_receiver;
};
void MyCtrl::OnClick()
{
m_receiver -> OnMyCtrlClick();
}
使用接口是OO设计最基本的原则之一,然而在我们的实际开发中,往往得不到贯彻。
五.总是使用指针或引用
这个问题看似和代码的复用无关。比如说一个函数:
void my_function(const string &str);以上是最常见的写法。为何不能写成:
void my_function(string str)许多人都知道这个道理。把对象直接放入函数接口中,结果这些对象将整个被压栈,出栈,内存操作往往比单独操作指针大了许多,这个消耗是完全没有必要的。此外,类似下面的写法:
vector< MyCfgItem > items;也曾经在我们的Capsuit项目中经常出现。这样用法也是有理由的:
map<string, MyCondition > conditons;
“这样使用起来方便。不用new,不用判断内存是否足够。不用delete,用delete的话万一忘记了就会内存泄漏。要说效率的话,拷贝内存,能有多少效率问题呢?”
如果MyCfgItem内部结构不复杂,确实效率问题并不是很大。但是这样使用一旦形成习惯,在MyCfgItem中再内含一个vector < MyClassB >,然后在MyClassB中再内含一个vector< MyClassA > 也是完全有可能的。这样一下来,多重拷贝,其效率的损失,就非常的客观了。与其到出了问题再手忙脚乱的修改代码,何如一开始就注意最基本的原则呢。
原则4 除非是轻量级的常用类,否则我们永远只使用类的对象的指针。
我个人认为,string这样的常用的stl模板类,又并非巨大的字符串的情况下,使用对象尚是可以接受到。但是自己开发的类,或者是使用别人开发的类无疑应该使用指针。这不仅仅是效率的问题。下面的写法才是合理的:
vector< MyCfgItem* > items;为何说不仅仅是效率的问题,我们再看下面的例子:
map<string, MyCondition* > conditons;
下面再举我们在Capsuit的开发中,碰到的一个问题。情况是这样的:我们的软件,要对计算机进行全面的检查。包括检查硬件,检查操作系统信息,检查注册表,检查进程,以及运行的服务等等,来判断当前计算机是否正常。本人负责开发检查部分。这个部分的任务是,根据外部输入的需求,来调用相应的实际进行检查的函数。这些函数则由各个不同部门的同仁实现好。本人只要调用他们就可以了。
外部总是输入一组条件:假设每个条件是这样的:
struct condition {
string check_type; // 告诉我检查的类型,
string param1; // 检查的参数,比如说是哪个注册表项要检查,等等
string param2; // 同上,都是取决于不同类型的检查而不同的参数
};