我一直在为 Windows 开发一个 GUI 库(作为个人业余项目,不希望有用)。对于我的主窗口类,我设置了选项类的层次结构(使用命名参数惯用语 http://www.parashift.com/c++-faq-lite/named-parameter-idiom.html),因为某些选项是共享的,而其他选项则特定于特定类型的窗口(如对话框)。
命名参数习惯用法的工作方式是,参数类的函数必须返回它们所调用的对象。问题是,在层次结构中,每个人都必须是一个不同的类——createWindowOpts
标准窗口类,createDialogOpts
对话框类等。我已经通过制作所有选项类模板来解决这个问题。这是一个例子:
template <class T>
class _sharedWindowOpts: public detail::_baseCreateWindowOpts {
public: ///////////////////////////////////////////////////////////////
// No required parameters in this case.
_sharedWindowOpts() { };
typedef T optType;
// Commonly used options
optType& at(int x, int y) { mX=x; mY=y; return static_cast<optType&>(*this); }; // Where to put the upper-left corner of the window; if not specified, the system sets it to a default position
optType& at(int x, int y, int width, int height) { mX=x; mY=y; mWidth=width; mHeight=height; return static_cast<optType&>(*this); }; // Sets the position and size of the window in a single call
optType& background(HBRUSH b) { mBackground=b; return static_cast<optType&>(*this); }; // Sets the default background to this brush
optType& background(INT_PTR b) { mBackground=HBRUSH(b+1); return static_cast<optType&>(*this); }; // Sets the default background to one of the COLOR_* colors; defaults to COLOR_WINDOW
optType& cursor(HCURSOR c) { mCursor=c; return static_cast<optType&>(*this); }; // Sets the default mouse cursor for this window; defaults to the standard arrow
optType& hidden() { mStyle&=~WS_VISIBLE; return static_cast<optType&>(*this); }; // Windows are visible by default
optType& icon(HICON iconLarge, HICON iconSmall=0) { mIcon=iconLarge; mSmallIcon=iconSmall; return static_cast<optType&>(*this); }; // Specifies the icon, and optionally a small icon
// ...Many others removed...
};
template <class T>
class _createWindowOpts: public _sharedWindowOpts<T> {
public: ///////////////////////////////////////////////////////////////
_createWindowOpts() { };
// These can't be used with child windows, or aren't needed
optType& menu(HMENU m) { mMenuOrId=m; return static_cast<optType&>(*this); }; // Gives the window a menu
optType& owner(HWND hwnd) { mParentOrOwner=hwnd; return static_cast<optType&>(*this); }; // Sets the optional parent/owner
};
class createWindowOpts: public _createWindowOpts<createWindowOpts> {
public: ///////////////////////////////////////////////////////////////
createWindowOpts() { };
};
它可以工作,但正如您所看到的,它需要大量的额外工作:每个函数的返回类型的类型转换、额外的模板类等等。
我的问题是,在这种情况下是否有一种更简单的方法来实现命名参数惯用语,不需要所有额外的东西?
也许不是您想听到的,但我认为在库代码中(或多或少)对客户端隐藏的大量丑陋的类型转换和模板参数是可以的只要这是安全的and使客户的生活变得更加轻松。库代码的美妙之处不在于代码本身,而在于它使客户端能够编写的代码。以STL为例。
我还开发了一个小型 GUI 库作为个人项目,与您的愿望基本相同,其中一些代码变得非常丑陋,但最终它允许我编写漂亮的客户端代码(至少在我的(可能是变态的)眼睛)这才是重要的恕我直言。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)