Heredar de la clase abstracta de plantilla

Nov 24 2020

Tengo esta estructura de código:

  • Una clase abstracta A (tiene un método virtual puro)
  • Una plantilla de clase B que hereda de A
  • Una plantilla de clase C que hereda de B
class A
{
protected:
    int u;
    int z;

public:
    A(int uu,
      int zz)
    :u(uu),
     z(zz)
    {};

    int get() const
    {
    return u;
    };

    virtual void blah() = 0;
};

template <class T>
class B : public A
{
protected:
    std::vector<T> xxxx;
public:
    B(int uu,
      int zz,
      int bbb)
    :A(uu,
       zz)
    {
    for(size_t i = 0; i < bbb; i ++)
        xxxx[i] = 0;
    };

    virtual void blah()
    {
    u = u + 1;
    };
};

template <class T>
class C : public B<T>
{
protected:
    int qrqr;

public:
    C(int uu,
      int zz,
      int bbb,
      int qrqrqr)
    :B<T>(uu,
          zz,
          bbb),
     qrqr(qrqrqr)
    {
    };

    virtual void blah()
    {
    u = u + qrqr;
    };
};

Cuando compilo obtengo este error:

 
error: 'u' was not declared in this scope
    at line:  u = u + qrqr;

Aunque ues claramente un elemento de C porque A es una base de C a B.

Leí aquí: Herencia de plantilla de clase C ++ que la forma correcta de heredar de la plantilla de clase es especializar la clase o hacer que la clase heredada sea plantilla y esto es lo que hice aquí. El compilador no parece quejarse de ello de todos modos. ¿Podría ser porque A es una clase abstracta?

¿Qué hice mal?

¡Gracias!

Respuestas

1 AmiTavory Nov 24 2020 at 16:08

Este es un problema con un nombre no dependiente : el miembro al que se refiere no depende del parámetro de plantilla. El compilador no busca en clases base dependientes (como B<T>) cuando busca nombres no dependientes (como u).

Puedes resolverlo usando

this->u = this->u + qrqr;

que especifica al compilador al que ute refieres.

( coliru )

Hay al menos otras dos formas, llamando B<T>::uo escribiendo using B<T>::u;en la función antes de esta línea.

Lea más sobre esto aquí .