不继承直接访问class接口中成员的成员
Directly access members of members in a class interface without inheritance
我面临的问题是,在我的应用程序中,class 的成员在构造函数中的初始化顺序很重要。因此我需要使用笨拙的语法来获得我想要的行为。
这应该概述了我的问题(见下面的代码):我希望我的 class Widget
从用户的角度包括 class WidgetSignals
的界面。我不能使用继承,因为这需要我在 Widget
的成员 elements
之前初始化继承的 WidgetSignals
应该用于初始化 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))
};
这是我以前解决这个问题的方法:
使用中介助手class:
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
};
通过这两种解决方案,我可以通过 Widget
:
使用 WidgetSignals
的界面
Widget widget(vec4(0, 0, 20, 5));
foo(widget.enter);
但是这两个解决方案都相当笨拙和混乱,所以我真的很想有一个更好的语法,比如:
using signals;
或
using signals::enter;
在 Widget
中。 using WidgetSignals<Elems...>::enter;
实际上是可行的,但前提是 Widget
已经继承自 WidgetSignals
,这意味着我必须再次使用中介助手 class,我希望如此避免。
只需将您要首先初始化的元素粘贴到您首先继承的 [private
] 基础 class 中。例如:
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) {
}
};
As base classes as inherited left-to-right/top-to-bottom 这安排 elements
成员在访问时初始化。唯一可能需要注意的是 virtual
碱基首先被初始化:如果 WdigetSignals
是一个 virtual
碱基,可能需要在 WidgetPbase
前面加上一个 virtual
.
我面临的问题是,在我的应用程序中,class 的成员在构造函数中的初始化顺序很重要。因此我需要使用笨拙的语法来获得我想要的行为。
这应该概述了我的问题(见下面的代码):我希望我的 class Widget
从用户的角度包括 class WidgetSignals
的界面。我不能使用继承,因为这需要我在 Widget
的成员 elements
之前初始化继承的 WidgetSignals
应该用于初始化 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))
};
这是我以前解决这个问题的方法:
使用中介助手class:
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
};
通过这两种解决方案,我可以通过 Widget
:
WidgetSignals
的界面
Widget widget(vec4(0, 0, 20, 5));
foo(widget.enter);
但是这两个解决方案都相当笨拙和混乱,所以我真的很想有一个更好的语法,比如:
using signals;
或
using signals::enter;
在 Widget
中。 using WidgetSignals<Elems...>::enter;
实际上是可行的,但前提是 Widget
已经继承自 WidgetSignals
,这意味着我必须再次使用中介助手 class,我希望如此避免。
只需将您要首先初始化的元素粘贴到您首先继承的 [private
] 基础 class 中。例如:
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) {
}
};
As base classes as inherited left-to-right/top-to-bottom 这安排 elements
成员在访问时初始化。唯一可能需要注意的是 virtual
碱基首先被初始化:如果 WdigetSignals
是一个 virtual
碱基,可能需要在 WidgetPbase
前面加上一个 virtual
.