关于函数返回值的设计的一些思考
作者:朱金灿
最近对函数返回值的设计有了一些新的思考。前一阵子头检查我写的代码。我的代码大致如下(凭记忆):
#include <stdio.h>
#include <float.h>
#include <string>
using std::string;
#include <vector>
using std::vector;
/*! @struct stExtent
* @brief
*
* 地理范围结构体,实现对地理范围的各种操作,如合并
* @author zjc
* @version 0.1
* @date 2010.08.10
*/
struct stExtent
{
stExtent()
{
m_fMinX = -FLT_MAX;
m_fMaxX = FLT_MAX;
m_fMinY = -FLT_MAX;
m_fMaxY = FLT_MAX;
}
/*!
* @brief 合并两个地理范围
*
* @param [in]Other 另一个地理范围
* @return 新的地理范围
*/
stExtent operator + (stExtent &Other)
{
m_fMinX = std::min(m_fMinX,Other.m_fMinX);
m_fMaxX = std::max(m_fMaxX,Other.m_fMaxX);
m_fMinY = std::min(m_fMinY,Other.m_fMinY);
m_fMaxY = std::max(m_fMaxY,Other.m_fMaxY);
return *this;
}
void operator = (stExtent &Other)
{
m_fMinX = Other.m_fMinX;
m_fMaxX = m_fMaxX,Other.m_fMaxX;
m_fMinY = m_fMinY,Other.m_fMinY;
m_fMaxY = m_fMaxY,Other.m_fMaxY;
}
/**
* @brief X方向的最小值
*/
float m_fMinX;
/**
* @brief X方向的最大值
*/
float m_fMaxX;
/**
* @brief Y方向的最小值
*/
float m_fMinY;
/**
* @brief Y方向的最大值
*/
float m_fMaxY;
};
/*! @class CDrawObj
* @brief
*
* 显示对象基类
* @author zjc
* @version 0.1
* @date 2010.08.10
*/
class CDrawObj
{
public:
CDrawObj()
{
m_Extent.m_fMinX = 0.0f;
m_Extent.m_fMinY = 0.0f;
m_Extent.m_fMaxX = 100.0f;
m_Extent.m_fMaxY = 100.0f;
}
/*!
* @brief 获取显示对象的地理范围
* @return 显示对象的地理范围
*/
stExtent& GetExtent()
{
return m_Extent;
}
protected:
private:
/**
* @brief 显示属性数组
*/
std::vector<stProperty> m_vecPropertys;
/**
* @brief 地理范围
*/
stExtent m_Extent;
};
/*! @class CDrawObj
* @brief
*
* 显示对象基类
* @author zjc
* @version 0.1
* @date 2010.08.10
*/
class CDrawObj
{
public:
CDrawObj()
{
m_Extent.m_fMinX = 0.0f;
m_Extent.m_fMinY = 0.0f;
m_Extent.m_fMaxX = 100.0f;
m_Extent.m_fMaxY = 100.0f;
}
/*!
* @brief 获取显示对象的地理范围
* @param Extent 求取的地理范围
* @return 显示对象的地理范围
*/
void GetExtent(stExtent& Extent)
{
Extent = m_Extent;
}
protected:
private:
/**
* @brief 显示属性数组
*/
std::vector<stProperty> m_vecPropertys;
/**
* @brief 地理范围
*/
stExtent m_Extent;
};
头建议我将CDrawObj类的GetExtent函数改为如下:
stExtent& GetExtent()
{
return m_Extent;
}
我说:"这样是为了方便实现链式表达式吗?"我的意思是:照头的改法,外部可以这样调用:stExtent TmpExtent = Obj1. GetExtent() + Obj1. GetExtent();头说:"不完全是,你想照你的做法,用户必须先定义一个stExtent变量,再把它传进函数。"我说:"这源于我的习惯认识,我认为renturn 返回的值用于判断操作是否成功"。不过这次头确实说的有道理,因为这个操作的返回值是void,那么直接返回操作结果值更为合理。
今天见到这样一个类的函数这样写:
struct stProperty
{
stProperty()
{
m_strName = _T("");
}
/**
* @brief 显示属性名
*/
std::string m_strName;
};
/*!
* @brief 给出一个属性名字,查找这个属性
*
* @param [in]strProName 给定的属性名字
* @return 属性
*/
stProperty Invalid_Property;
stProperty SearchProperty(const std::string strProName) const
{
//m_vecPropertys为一个类的属性数组先循环属性数组,找出符合条件的数组,
// 若不存在,抛出异常并返回错误属性
try
{
for (size_t i =0;i<m_vecPropertys.size();i++)
{
if (strProName==m_vecPropertys[i].m_strName)
{
return m_vecPropertys[i];
}
}
}
catch (...)
{
}
throw _T("cannot find Property");
return Invalid_Property;
}
我觉得这样设计并不合理,如果让我设计的话,我会这样设计这个函数:
BOOL SearchProperty(const std::string strProName,stProperty &prop),
用BOOL变量返回值来判断是否存在这样的属性,用变量prop来保存查找结果。
为此我总结了一下设计函数的一些心得:首先判断是否需要操作是否成功、值是否存在,若不需要,考虑直接返回操作结果(即由renturn语句返回而不是通过输出参数返回),毕竟这样外部调用比较方便,若需要,则应设计为通过输出参数返回操作结果值。
补充:软件开发 , C语言 ,