في C++، هل يمكنك توسيع فئة أساسية ذات معلمات بقيمة معلمة مختلفة في الفئة الفرعية؟

StackOverflow https://stackoverflow.com/questions/2009295

سؤال

في جميع اللغات التي أفهمها، هذا غير ممكن ولكن أخبرني أحدهم أنه ممكن في لغة C++ ولكني أجد صعوبة في تصديق ذلك.بشكل أساسي، عند تحديد معلمات فصل دراسي، فإنك تقوم بإنشاء فصل فريد في مرحلة التجميع، أليس كذلك؟

اسمحوا لي أن أعرف إذا لم أكن واضحا مع سؤالي.

هذه محاولتي لشرح ما أحاول القيام به ( انتبه للفئة L ):

//; g++ ModifingBaseClassParameter.cpp -o ModifingBaseClassParameter;ModifingBaseClassParameter

#include <iostream>

using namespace std;

template<typename T>
class Base
{
    public:
        Base() {}
        Base(T& t) : m_t(t) {}
        T& getMem() {return m_t;}
    private:
        T m_t;
};

template<typename T>
class F: Base<T>
{};

template<typename T>
class L: F<long>
{};

int main()
{
     Base<int> i;
     F<float> f;
     L<long> l;

     cout<<i.getMem()<<endl;
//     cout<<f.getMem()<<endl; // why doesn't this work
//     cout<<l.getMem()<<endl; // why doesn't this work
}

لذا كما ترون (آمل أن يكون بناء الجملة الخاص بي منطقيًا) تحاول الفئة L إعادة تعريف المعلمة العائمة الخاصة بوالدها لتكون طويلة.بالتأكيد لا يبدو أن هذا قانوني ولكني سأختلف مع الخبراء.

هل كانت مفيدة؟

المحلول

إذا كنت تقصد أن تسأل ما إذا كان يمكنك القيام بذلك في C ++:

template <> 
class ParamClass<Type1> : public ParamClass<Type2> 
{
};

ثم نعم، فمن الممكن.

غالبا ما يتم استخدامه، على سبيل المثال لتحديد قوائم القالب أو يرث سمات من نوع آخر.

نصائح أخرى

ما طلبته لا يمكن القيام به مباشرة - ولكن يمكنك أن تأتي قريبا جدا باستخدام معلمة قالب افتراضية:

template <typename T>
class Base { };

template <typename T = int>
class X : Base<T> {};

class Y : Base<float>

class Z : X<long> {};

في هذه الحالة بالذات، لا تضيف معلمة القالب الافتراضي الكثير. يجب عليك توفير قائمة معلمة قالب لإرساء القالب، حتى إذا تم توفير الإعدادات الافتراضية لجميع المعلمات. على هذا النحو، فإن وجود افتراضي يتجاوز في فئة مشتقة عادة ما يكون مفيدا فقط للمعلمات الثانية واللاحقة.

#include <iostream>
#include <typeinfo>

using namespace std;

template<typename T>
class Base
{
    public:
        Base() {}
        Base(T& t) : m_t(t) {}
        T& getMem() {return m_t;}
    private:
        T m_t;
};

template<typename T>
class F: public Base<T>
{};

template<typename T>
class L: public F<long>
{};

int main()
{
     Base<int> iNTEGER;
     F<float> fLOAT;
     L<long> lONG;

     int x;
     cout << typeid(iNTEGER.getMem()).name() << endl;
     cout << typeid(fLOAT.getMem()).name() <<endl; // this works now :)
     cout << typeid(lONG.getMem()).name() <<endl; // this works now :)
}

يكون الميراث خاصًا بشكل افتراضي في c++، بمجرد الإعلان عن ما كتبه stephenmm يجب أن يعمل إلا إذا كنت تقصد طرح شيء آخر؟

هل تأخذ حول القوالب؟

template<typename T>
class Base
{
    public:
        Base() {}
        Base(T& t) : m_t(t) {}
        T& getMem() {return m_t;}
    private:
        T m_t;
};

class X: Base<int>
{};

class Y: Base<float>
{};

يجب أن تحاول تجميعها:

$ g++ so-test1.c++ -o so-test1.c++ && ./so-test
so-test1.c++:21: error: expected template-name before ‘<’ token
so-test1.c++:21: error: expected `{' before ‘<’ token
so-test1.c++:21: error: expected unqualified-id before ‘<’ token
so-test1.c++: In function ‘int main(int, const char**)’:
so-test1.c++:27: error: aggregate ‘Z z’ has incomplete type and cannot be defined

X ليس قالب فئة، لذلك لا معنى له في محاولة إنشاء مثيل

class Z: X<long> {};

X لا يوجد لديه معلمات قالب لتجاوز. تذكر ذلك

Base<int>

ليس قالب فئة إما؛ إنها فئة بحقها، ولكن مثيل له تماما. من قالب. يمكنك القيام بذلك:

....
template<typename T>
class X: Base<T> 
{};
...
class Z: X<long> 
{};

ولكن هنا لا يوجد ارتباك حول تجاوز أي معلمات القالب.

template<typename T>
class X: Base<int> 
{};
...
class Z: X<long>
{};

يعمل أيضا، ولكن هنا معلمة القالب في X غير مستخدمة، ولا يتم تجاوز شيء.

هذر

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top