Em C ++ você pode estender uma classe base parametrizada com diferente valor de parâmetro na classe filho?

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

Pergunta

Em todas as línguas que eu entendo isso não é possível, mas alguém estava me dizendo que era possível em C ++, mas eu tenho um tempo difícil acreditar. Essencialmente quando você parametrizar uma classe que você está criando uma classe única na fase de compilação não é?

Deixe-me saber se eu não estou sendo claro com a minha pergunta.

Aqui está a minha tentativa de explicando o que eu estou tentando fazer (prestar atenção à classe 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
}

Então, como você pode ver (espero que a minha sintaxe faz sentido) classe L está tentando redefinir parâmetro flutuador do seu pai para ser um longo. Ele certamente não parece que isso é legal, mas eu será diferente para os especialistas.

Foi útil?

Solução

Se você quer dizer para perguntar se você pode fazer isso em C ++:

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

então sim, é possível.

É muito frequentemente utilizado, por exemplo, para definir listas de template ou traços herdar de outro tipo.

Outras dicas

O que você pediu não pode ser feito diretamente - mas você pode vir muito perto usando um parâmetro de modelo padrão:

template <typename T>
class Base { };

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

class Y : Base<float>

class Z : X<long> {};

Neste caso particular, o parâmetro modelo padrão não acrescenta muito. Você tem que fornecer uma lista de parâmetros de modelo para instanciar um modelo, mesmo que os padrões são fornecidos para todos os parâmetros. Como tal, ter um padrão que você substituir em uma classe derivada normalmente só é útil para o segundo e subseqüentes parâmetros.

#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 :)
}

a herança é privado por padrão em C ++, uma vez tornado público que stephenmm escreveu deve funcionar a menos que você queria perguntar outra coisa?

Você está tomando sobre modelos?

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>
{};

Você deve tentar compilá-lo:

$ 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 não é um modelo de classe, por isso não faz sentido tentar instanciar-lo em

class Z: X<long> {};

X não tem parâmetros do modelo para substituir. Lembre-se que

Base<int>

não é um modelo de classe quer; é uma classe em seu próprio direito, mas totalmente instanciado de um modelo. Você poderia fazer isso:

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

Mas aqui não há confusão sobre a substituição de quaisquer parâmetros do modelo.

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

funciona também, mas aqui o parâmetro do modelo em X não é usado, e nada é substituído.

HTH

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top