由於您使用的模板,我在想,你對防止超過來源於基地繼承其他任何一類問題的最後一部分可以用適當的部分特例來完成。
下面的代碼片段是我想出來的,但所需的複雜性只能通過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