假设我有下面的类X,我想返回一个内部成员的访问:
class Z
{
// details
};
class X
{
std::vector<Z> vecZ;
public:
Z& Z(size_t index)
{
// massive amounts of code for validating index
Z& ret = vecZ[index];
// even more code for determining that the Z instance
// at index is *exactly* the right sort of Z (a process
// which involves calculating leap years in which
// religious holidays fall on Tuesdays for
// the next thousand years or so)
return ret;
}
const Z& Z(size_t index) const
{
// identical to non-const X::Z(), except printed in
// a lighter shade of gray since
// we're running low on toner by this point
}
};
两个成员函数X::Z()和X::Z() const在大括号内具有相同的代码。这是重复的代码,可能会导致具有复杂逻辑的长函数的维护问题。
有办法避免这种代码重复吗?
您还可以使用模板来解决这个问题。这个解决方案略显丑陋(但丑陋之处隐藏在.cpp文件中),但它确实提供了编译器对一致性的检查,并且没有代码重复。
. h文件:
#include <vector>
class Z
{
// details
};
class X
{
std::vector<Z> vecZ;
public:
const std::vector<Z>& GetVector() const { return vecZ; }
std::vector<Z>& GetVector() { return vecZ; }
Z& GetZ( size_t index );
const Z& GetZ( size_t index ) const;
};
保护作用:文件。
#include "constnonconst.h"
template< class ParentPtr, class Child >
Child& GetZImpl( ParentPtr parent, size_t index )
{
// ... massive amounts of code ...
// Note you may only use methods of X here that are
// available in both const and non-const varieties.
Child& ret = parent->GetVector()[index];
// ... even more code ...
return ret;
}
Z& X::GetZ( size_t index )
{
return GetZImpl< X*, Z >( this, index );
}
const Z& X::GetZ( size_t index ) const
{
return GetZImpl< const X*, const Z >( this, index );
}
我能看到的主要缺点是,由于该方法的所有复杂实现都在一个全局函数中,您要么需要使用上面的GetVector()这样的公共方法获取X的成员(其中总是需要一个const版本和非const版本),要么可以将此函数作为朋友。但是我不喜欢朋友。
[编辑:删除了测试期间添加的不需要的cstdio。]
我建议使用私有helper静态函数模板,如下所示:
class X
{
std::vector<Z> vecZ;
// ReturnType is explicitly 'Z&' or 'const Z&'
// ThisType is deduced to be 'X' or 'const X'
template <typename ReturnType, typename ThisType>
static ReturnType Z_impl(ThisType& self, size_t index)
{
// massive amounts of code for validating index
ReturnType ret = self.vecZ[index];
// even more code for determining, blah, blah...
return ret;
}
public:
Z& Z(size_t index)
{
return Z_impl<Z&>(*this, index);
}
const Z& Z(size_t index) const
{
return Z_impl<const Z&>(*this, index);
}
};