由于您使用的模板,我在想,你对防止超过来源于基地继承其他任何一类问题的最后一部分可以用适当的部分特例来完成。
下面的代码片段是我想出来的,但所需的复杂性只能通过jalf来加强答案。这值得么?如果这有助于我理解部分专业化,而不是制定一种我将在实践中使用的技术。
我用普通的指示基类和派生和EXTRA表示,你说派生有额外的参数之间的共享模板参数。这些的实际数量可能是我刚刚碰巧分别挑选了一个和两个的任何数量。
// Forward declaration of class Derived
template< class COMMON
, class EXTRA1
, class EXTRA2 >
class Derived;
// Definition of general class template Base
template< class SUBCLASS
, class COMMON >
class Base
{
private:
Base() {}
};
// Definition of partial specialisation of template class Base to open up
// access to the constructor through friend declaration.
template< class COMMON
, class EXTRA1
, class EXTRA2 >
class Base< Derived< COMMON, EXTRA1, EXTRA2 >
, COMMON >
{
private:
Base() {}
friend class Derived< COMMON, EXTRA1, EXTRA2 >;
};
// Definition of class Derived
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 >()
{
}
};
// Definition of class HonestDerived.
// It supplies itself as the SUBCLASS parameter to Base.
template < class COMMON
, class EXTRA1
, class EXTRA2 >
class HonestDerived
: public Base< HonestDerived< COMMON, EXTRA1, EXTRA2 >
, COMMON >
{
public:
HonestDerived() : Base< HonestDerived< COMMON, EXTRA1, EXTRA2 >
, COMMON >()
{
}
};
// Definition of class DishonestDerived
// It supplies Derived rather than itself as the SUBCLASS parameter to Base.
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 >()
{
}
};
// Test partial specialisation gives Derived access to the Base constructor
Derived< int, float, double >* derived
= Derived< int, float, double >::create();
// Test that there is no access to the Base constructor for an honest subclass
// i.e. this gives a compiler error
HonestDerived< int, float, double > honestDerived;
// Test that there is no access to the Base constructor for a dishonest subclass
// i.e. this gives a compiler error
DishonestDerived< int, float, double > dishonestDerived;
// Test that there is no access to the Derived constructor
// i.e. this gives a compiler error
DerivedFromDerived< int, float, double > derivedFromDerived;
这段代码是用gcc 4.3.2测试的。
注意,对朋友声明的替代方案是使基地的部分特保护的构造函数,但随后将允许像DishonestDerived类的工作。
我会包含一些源代码 - 因为它涉及到模板。 – sylvanaar 2009-08-07 21:44:31
如果一个类没有虚拟析构函数,那么你可能不应该从这个虚拟析构函数中删除它(这只是一个好的编程)。 C++认识到有时你需要扩展边界的能力,并让你从中继承。所以你问题不是一个教育的语言。 – 2009-08-08 01:00:03
投票:删除关键字/最终标签,但添加** derived-class **标签代替 – fmuecke 2009-12-08 11:03:14