テンプレートを使用しているので、私は、Derived以外のクラスをBaseからサブクラス化することについての質問の最後の部分は、適切な部分的な特殊化を使用して行うことができると考えていました。
次のコードスニペットは私が思いついたものですが、複雑さが必要なのはjalfの答えを強化するためだけです。その価値はありますか?何かがあれば、実際に使っていた技術を開発するよりも、部分的な専門化を理解するのに役立ちました。
私はCOMMONを使用して、BaseとDerivedの間の共有テンプレートパラメータを示し、EXTRAを使用して、Derivedが持つ追加のパラメータを示します。これらの実際の数は、ちょうど私がこれらのためにそれぞれ1つと2つを選んだことがあります。
// 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でテストされています。
フレンド宣言の代わりに、Baseの部分的な特殊化でコンストラクタを保護することができますが、DishonestDerivedなどのクラスが動作するようにすることができます。C++ 11のよう
テンプレートが含まれているので、私はいくつかのソースコードを含めることにします。 – sylvanaar
クラスに仮想デストラクタがない場合は、おそらくそれを使っていないはずです。 C++では、境界線をストレッチする能力が必要な場合があり、とにかにそれを継承することができることを認識しています。だから問題は、教育的なものを置く言語ではない。 –
投票:キーワード/最終タグを削除しますが、代わりに**派生クラス**タグを追加してください – fmuecke