由于您正在使用模板,我认为您关于防止除Derived以外的任何类从Base派生的最后一部分问题可以使用适当的部分特化来解决。
以下代码片段是我想出来的,但所需的复杂性只能加强jalf的答案。这值得吗?如果有什么问题,这帮助我更好地理解了部分特化,而不是找出我在实践中永远不会使用的技术。
我使用COMMON来表示Base和Derived之间共享的模板参数,EXTRA表示您说Derived具有的额外参数。它们的实际数量可以是任何数字,我只是恰好选择了一个和两个。
template< class COMMON
, class EXTRA1
, class EXTRA2 >
class Derived;
template< class SUBCLASS
, class COMMON >
class Base
{
private:
Base() {}
};
template< class COMMON
, class EXTRA1
, class EXTRA2 >
class Base< Derived< COMMON, EXTRA1, EXTRA2 >
, COMMON >
{
private:
Base() {}
friend class Derived< COMMON, EXTRA1, EXTRA2 >;
};
template < class COMMON
, class EXTRA1
, class EXTRA2 >
class Derived
: public Base< Derived< COMMON, EXTRA1, EXTRA2 >
, COMMON >
{
public:
static Derived* create() { return new Derived; }
private:
Derived() : Base< Derived< COMMON, EXTRA1, EXTRA2 >
, COMMON >()
{
}
};
template < class COMMON
, class EXTRA1
, class EXTRA2 >
class HonestDerived
: public Base< HonestDerived< COMMON, EXTRA1, EXTRA2 >
, COMMON >
{
public:
HonestDerived() : Base< HonestDerived< COMMON, EXTRA1, EXTRA2 >
, COMMON >()
{
}
};
template < class COMMON
, class EXTRA1
, class EXTRA2 >
class DishonestDerived
: public Base< Derived< COMMON, EXTRA1, EXTRA2 >
, COMMON >
{
public:
DishonestDerived() : Base< Derived< COMMON, EXTRA1, EXTRA2 >
, COMMON >()
{
}
};
template< class COMMON, class EXTRA1, class EXTRA2 >
class DerivedFromDerived
: public Derived< COMMON, EXTRA1, EXTRA2 >
{
public:
DerivedFromDerived() : Derived< COMMON, EXTRA1, EXTRA2 >()
{
}
};
Derived< int, float, double >* derived
= Derived< int, float, double >::create();
HonestDerived< int, float, double > honestDerived;
DishonestDerived< int, float, double > dishonestDerived;
DerivedFromDerived< int, float, double > derivedFromDerived;
这段代码已经在gcc 4.3.2上进行了测试。
请注意,与friend声明的替代方案是将Base的部分特化中的构造函数设置为protected,但这样会允许像DishonestDerived这样的类正常工作。