nim_duilib(18)之xml控件关联优化

方法1

直接调用函数FindControl函数,返回Control*类型,对返回的类型强制转换

ui::CheckBox* pcheckbox = (ui::CheckBox*)(FindControl(L"checkbox1"));

典型C的强制转换。

方法2

使用C++关键字dynamic_cast完成转换,一个例子

ui::CheckBox* pcheckbox = dynamic_cast<ui::CheckBox*>(FindControl(L"checkbox1"));

很明显,增加了类型转换。

方法1 和 方法2的缺点

要写很多代码;当界面控件多了以后, 每个控件关联都需要调用函数FindControl,完成绑定,代码量增加。
我们可以采用C++11新特性实现优化。

C++11优化

思考

我们可以写一个函数,函数体内完成下面两件事

  • 查找xml中的控件
  • Control* 转为目标类型
    通过对比可以发现,关联控件所用的代码重复率高,采用模板,实现优化。

方案1

设计函数

  • 函数返回值为目标类型的指针变量。 用事先声明在类中的成员变量保存即可
  • 通过函数参数的方式传递目标类型。
    函数源码如下:
	template<typename T>
	auto find_control(const std::wstring&& str_name, T args)
	{
		// 取得传进来的参数类型
		using ele_type = decltype(args) ;

		// 读取xml文件中的控件
		ui::Control* pctrl = nullptr;
		pctrl = FindControl(str_name);
		if (pctrl)
		{
			// 转为目标类型指针
			args = dynamic_cast<ele_type>(pctrl);
		}

		return args;
	}

目标控件类型不确定,所以,采用关键字auto自动推导。 调用代码如下:

	ui::Button *pbtntmp = nullptr;
	ui::Button *pbutton = find_control(std::wstring(L"btn_blue"), pbtntmp);

pbutton 函数的返回值。

分析

该方法看上去有所转变,但实际上没有任何意义,反而使得阅读性降低。

方案 2

方案1的基础上继续改进,调用函数时,将需目标变量也传进去。 这样,函数内部完成转换。 函数体如下:

// 取得传进来的参数类型
using ele_type2 =  typename std::decay<T>::type;

// 读取xml文件中的控件
ui::Control* pctrl = nullptr;
pctrl = FindControl(str_name);
if (pctrl)
{
	// 转为目标类型指针
	args = dynamic_cast<ele_type2>(pctrl);
}

这样,函数内部完成了转换,避免了接收函数的返回值。 调用示例。

// 定义了3个buttons
ui::Button	*pbtn_arr_[count_3];
find_control2(std::wstring(L"btn_blue"),	pbtn_arr_[0]);
find_control2(std::wstring(L"btn_white"),	pbtn_arr_[1]);
find_control2(std::wstring(L"btn_red"),		pbtn_arr_[2]);

瞧,相对方法1方法2 ,减少了不少代码量。

思考

当让,还可以继续优化。 比如, 伪代码 如下:

template<typename T>
void find_control(const  std::wstring name_arr[], T** t)
{
	// to do ...
}

将xml中的name和控件同时以数组传递到函数中,函数内完成转换

posted @ 2020-12-18 17:51  mohist  阅读(327)  评论(0编辑  收藏  举报