【发布时间】:2012-01-01 00:42:07
【问题描述】:
我的 Getter/Setter 方法在设置/返回之前检查值。当值无效时,它们会抛出异常(BadArgumentException 或 IllegalStateException)。这是必需的,因为我们使用无效值初始化所有成员 - 因此我们避免使用这些无效值(== 在其他地方出现错误/段错误/异常)。
好处是:
- 当您从模型收到成员值时,您就知道它们是有效的
- 有效性检查仅在模型对象中执行
- 值范围在模型对象中定义
这似乎很不寻常,因为大多数新团队成员首先抱怨它——即使在我向他们解释后他们同意我的看法。
问题:这是一种好的编程风格吗? (即使浪费一点性能)
示例代码:
inline bool MyClass::HasGroupID const { return m_iGroupID != 0; }
int MyClass::GetGroupID() const
{
if( !HasGroupID() )
throw EPTIllegalStateException( "Cannot access uninitialized group ID!" );
return m_iGroupID;
} // END GetGroupID() const
void MyClass::SetGroupID( int iGroupID )
{
// negative IDs are allowed!
if( iGroupID != 0 )
throw EPTBadArgumentException( "GroupID must not be zero!", iGroupID );
m_iGroupID = iGroupID;
} // END SetGroupID( int )
用法:
// in serialization
if( myObject.HasGroupID() )
rStream.writeAttribute( "groupid", GetGroupID() );
// in de-serialization
try {
// required attribute - throw exception if value is invalid
myObject.SetGroupID( rStream.GetIntegerAttribute( "groupid" );
} catch( EPTBadArgumentException& rException )
{
throw EPTBadXmlAttribute( fileName, rException );
}
【问题讨论】:
-
在大多数情况下这是一种非常好的编程风格。我强烈推荐。如果您使用数据库模型等也很好
-
我不认为到处都有无效的对象是一种好的风格。将事物初始化为有效值要好得多。
-
但是如果你用有效值初始化它们并忘记了 Setter() (例如在添加新成员之后 - 在克隆方法中,或在读入期间,或在复制构造函数中,赋值方法,等等)你会很晚才提到这个(而且大多数时候你不会知道这个错误来自哪里)。所以你会得到一个例外,而且它会很好地重现......
标签: c++ exception setter getter