我面临的问题是,在我的应用程序中,重要的是在构造函数中初始化类成员的顺序。因此,我需要使用笨拙的语法来获取我想要的行为。
这应该概述我的问题(请参见下面的代码):从用户的 Angular 来看,我希望class Widget
包括class WidgetSignals
的界面。我不能使用继承,因为这要求我在应用于初始化WidgetSignals
的elements
成员Widget
之前初始化继承的WidgetSignals
。
template<typename... Elems>
class WidgetSignals
{
WidgetSignals(const std::tuple<Elems...> elems)
: // initialize members using elems
{}
// members ...
};
template<typename... Elems>
class Widget : public WidgetSignals<Elems...>
{
std::tuple<Elems...> elements;
Widget(vec4 quad)
: WidgetSignals<Elems...>(elements) // uh-oh! elements are not initialized yet!
, elements(initalizeElements(quad))
};
这是我以前针对此问题的解决方案:
使用调解器助手类:
template<typename... Elems>
class Widget : public WidgetSignals<Elems...>
{
std::tuple<Elems...> elements;
struct Data
{
Data(vec4 quad)
: elems(initializeElements(quad)) // initialize elements here
{}
std::tuple<Elems...> elems;
};
Widget(Data data)
: WidgetSignals<Elems...>(data.elems) // bingo!
, elements(data.elems)
{}
};
封装
WidgetSignals
并在Widget中公开对WidgetSignals
'成员的引用:template<typename... Elems>
class Widget
{
std::tuple<Elems...> elements;
WidgetSignals<Elems...> signals;
Widget(vec4 quad)
: elements(initializeElements(quad))
, signals(elements) // initialized after elements because of order of member declaration
{}
// WidgetSignal member references
const typename WidgetSignals<Elems...>::SignalType& enter = signals.enter;
const typename WidgetSignals<Elems...>::SignalType& leave = signals.leave;
// ... remaining members
};
通过这两种解决方案,我然后可以通过
WidgetSignals
使用Widget
的接口(interface):Widget widget(vec4(0, 0, 20, 5));
foo(widget.enter);
但是这两种解决方案都相当笨拙且困惑,因此我真的很想为此提供更好的语法,例如:
using signals;
要么
using signals::enter;
在
Widget
中。 using WidgetSignals<Elems...>::enter;
实际上是可行的,但前提是Widget
已经从WidgetSignals
继承了,这意味着我不得不再次使用中介者帮助器类,我想避免这种情况。 最佳答案
只需将要初始化的元素放在首先继承的[private
]基类中即可。例如:
template<typename... Elems>
struct WidgetPbase {
std::tuple<Elems...> elements;
}
template<typename... Elems>
class Widget
: private WidgetPbase<Elems...>
, public WidgetSignals<Elems...>
{
public:
Widget(vec4 quad)
: WidgetPbase<Elems...>{initializeElements(quad)}
, WidgetSignals<Elems...>(elements) {
}
};
由于基类是从左到右/从上到下继承的,因此它安排了
elements
成员在其访问时被初始化。唯一的警告是,首先初始化virtual
基:如果WdigetSignals
是virtual
基,则可能有必要将virtual
粘贴在WidgetPbase
的前面。