困惑?我也是... 请考虑以下
var result = bazzers
.Select(bazzer => bazzer.Bar)
.Distinct()
.Select(bar => new
{
Bar = bar,
LoyalFoos = bazzers
.GroupBy(bazzer => bazzer.Foo)
.Where(group => group.All(bazzer => bazzer.Bar == bar))
.SelectMany(group => group)
});
以上工作正常,并在构造函数的成员初始化列表中初始化typedef std::map<std::string , double> Thresholds;
class Foo
{
public:
Foo( const double & _toxicThres , const double & _zeroThres )
: thresholds
(
MapInitializer<std::string , double>()
.Add("toxic" , _toxicThres)
.Add("zero" , _zeroThres)
)
private:
Thresholds thresholds;
};
。现在考虑一下:
std::map
请注意,typedef std::map<std::string , double> Thresholds;
struct CommonData
{
Thresholds thresholds;
};
class Foo //a mixin
{
public:
Foo( Thresholds & thresholds , const double & _toxicThres , const double & _zeroThres )
: thresholds
(
MapInitializer<std::string , double>()
.Add("toxic" , _toxicThres)
.Add("zero" , _zeroThres)
)
};
class Bar //another mixin
{
public:
Bar( Thresholds & thresholds , const double & _warningThres , const double & _zeroThres)
: thresholds
(
MapInitializer<std::string , double>()
.Add("warning" , _warningThres)
.Add("zero" , _zeroThres)
)
};
class OtherGasThreshold{/*...*/}; //yet another mixin, etc...
template<typename ThresholdMixin> //Foo , Bar , or others ...
class ThresholdSensor : public ThresholdMixin
{
public:
ThresholdSensor(double val1 , double val2)
: ThresholdMixin(cd.thresholds, val1 , val2)
{}
private:
CommonData cd;
};
代码来自here,而且是
MapIniializer
当然上面的代码不能编译,但是有没有办法在构造函数init期间在其中一个mixin中的template<class K, class V>
class MapInitializer
{
std::map<K,V> m;
public:
operator std::map<K,V>() const
{
return m;
}
MapInitializer& Add( const K& k, const V& v )
{
m[ k ] = v;
return *this;
}
};
中初始化地图。即我可以通过引用传递地图,在mixins构造函数中初始化它吗?
答案 0 :(得分:2)
基础子对象是在数据成员之前构建的,因此基本初始化程序通常不能使用派生数据成员。
我会保持简单并具有正常的成员函数:
struct Foo
{
void Init(Thresholds & thresholds)
{
thresholds.emplace("foo", 1.0);
thresholds.emplace("bar", 1.5);
}
// ...
};
template <typename Mx>
struct Thing : Mx
{
Thresholds thresholds;
Thing() { Mx::Init(thresholds); }
// ^^^^^^^^^^^^^^^^^^^^^
// ...
};
用法:
Thing<Foo> x;
答案 1 :(得分:1)
在有问题的构造函数中,thresholds
作为参数传递给构造函数。
初始化语法用于初始化超类和类成员。对于其他一切,这就是构造函数的主体所针对的:
class Bar
{
public:
Bar( Thresholds & thresholds,
const double & _warningThres,
const double & _zeroThres)
{
thresholds=MapInitializer<std::string , double>()
.Add("warning" , _warningThres)
.Add("zero" , _zeroThres)
}
};
此示例中没有超类或其他类成员,因此可以正常工作。我没有在您的示例中看到任何需要在构造函数的初始化部分初始化thresholds
的显式依赖项。
但是假设有。假设在thresholds
和超类或类成员之间存在某种依赖关系,并且由于某些未指定的依赖关系,在初始化另一个对象之前,首先需要初始化thresholds
。必须在构造函数的初始化部分初始化类成员或超类,因此我们也需要在那里初始化thresholds
。
如果我们使用一个具体的例子,那就容易多了:
class Bar
{
public:
Bar( Thresholds & thresholds,
const double & _warningThres,
const double & _zeroThres);
class private_bar {
public:
private_bar(Thresholds &thresholds);
};
private:
private_bar secret;
};
假设Bar
的构造函数需要构造secret
,但只有在初始化thresholds
之后,才会传递给private_bar
的构造函数。不难想象出现这种情况的情况。 private_bar
的构造函数使用初始化的thresholds
,就是这样。现在,您已在secret
的构造函数的初始化部分初始化Bar
成员,但在此之前需要初始化thresholds
。我相信这就是你的问题归结为。
在这种情况下,解决方案通常采用以下通用设计模式:
class Bar
{
static Thresholds &init_thresholds(Thresholds &thresholds)
{
thresholds=MapInitializer<std::string , double>()
.Add("warning" , _warningThres)
.Add("zero" , _zeroThres)
return thresholds;
}
public:
Bar( Thresholds & thresholds,
const double & _warningThres,
const double & _zeroThres)
: secret(init_thresholds(thresholds))
{
}
class private_bar {
public:
private_bar(Thresholds &thresholds);
};
private:
private_bar secret;
};
这就是“可以在类的构造函数列表中进行非成员初始化”,以回答您的问题。如果真的有必要这样做,那一定是因为首先需要在构造函数列表中初始化 else 。否则,您只需在主构造函数体中初始化它。
但是如果需要在构造函数列表中初始化其他东西,那么你只需“搭载”在该构造之上,以便使用辅助函数初始化非成员对象。