В C++ вы можете расширить параметризованный базовый класс с другим значением параметра в дочернем классе?

На всех языках, которые я понимаю, это невозможно, но кто-то говорил мне, что это возможно в 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 пытается переопределить параметр float своего родителя, чтобы он был длинным. Это, конечно, не кажется законным, но я буду отличаться от экспертов.

5 ответов

Решение

Если вы хотите спросить, можете ли вы сделать это в 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 не используется, и ничего не переопределяется.

НТН

Другие вопросы по тегам