Cuando una plantilla públicamente hereda de otra plantilla, no son la base de métodos públicos accesible?

template <int a>
class Test {
public:
    Test() {}
    int MyMethod1() { return a; }
};

template <int b>
class Another : public Test<b>
{
public:
    Another() {}
    void MyMethod2() {
        MyMethod1();
    }
};

int main()
{
    Another<5> a;
    a.MyMethod1();
    a.MyMethod2();
}

Bien, GCC juego de dados en esta… me debe faltar algo totalmente obvio (cerebro fundir). Ayuda?

  • Se perdió un punto y coma después de su segunda definición de la clase.
  • Le falta un ; al final de class Another. Si usted arreglar eso, entonces es la compilación de multa en VS2008
  • Que VC acepta esto es debido a que no implementación adecuada de las dos de la fase de búsqueda.
  • Por favor, intenta código postal que sólo tiene el problema que usted está interesado en. De lo contrario, obtendrá muchas respuestas señalando muchos otros problemas, también.
  • Cuando usted está haciendo una pregunta acerca de un error, usted debe publicar el mensaje de error.
  • Esto sucede debido a las dos de la fase de búsqueda de nombre (que no todos los compiladores utilizan por defecto). Hay 4 soluciones a este problema: 1) Usar el prefijo Test<a>::MyMethod1, 2) Usar el prefijo this->MyMethod1, 3) Agregar una declaración using Test<a>::MyMethod1, 4) el Uso de un mundial modificador de compilador que permite el modo permisivo. Los pros & contras y los detalles de estas soluciones se describen en stackoverflow.com/questions/50321788/…

InformationsquelleAutor OldCoder | 2009-10-14

5 Comentarios

  1. 31

    Esto es parte de las reglas relativas a los dependientes de los nombres. Method1 no es un dependiente nombre en el ámbito de Method2. Por lo que el compilador no la busque en dependiente de las clases base.

    Hay dos formas de arreglar eso: el Uso de this o especificando el tipo base. Más detalles sobre este muy reciente post o en el C++ FAQ. Observe también que se perdió la palabra clave pública y una semi-colon. He aquí una versión fija de su código.

    
    template <int a>
    class Test {
    public:
        Test() {}
        int MyMethod1() { return a; }
    };
    
    template <int b>
    class Another : public Test<b>
    {
    public:
        Another() {}
        void MyMethod2() {
            Test<b>::MyMethod1();
        }
    };
    
    int main()
    {
        Another<5> a;
        a.MyMethod1();
        a.MyMethod2();
    }
    
    • +1 para los enlaces.
    • Sí, esa es la respuesta correcta. (Tenga en cuenta que, TTBOMK, this->MyMethod1() también debería funcionar.)
    • Si usted piensa que es una locura que esto es necesario, usted no está solo. Aún así, es es un hecho triste de la vida.
    • +1. También vale la pena leer es el de plantillas de C++ FAQ: womble.decadentplace.org.reino unido/c++/template-faq.html muy bonito!
    • Que buena, litb. Yo no sabía el sitio de Ben.
    • También es posible declarar using Test<b>::MyMethod1() en algún lugar en class Another.

  2. 14

    Usted debe calificar totalmente MyMethod1. El Estándar de C++ establece claramente esta en 14.6.2/3:

    En la definición de una plantilla de clase o un miembro de una plantilla de clase, si una clase base de la clase de plantilla depende de una plantilla de parámetros, la base ámbito de la clase no es examinada durante incondicional en la búsqueda del nombre, ya sea en el punto de la definición de la plantilla de clase o miembro o durante una instanciación de la clase de plantilla o de los miembros.

    Así, usted debe escribir:

    void MyMethod2() {
        Test<b>::MyMethod1();
    }
  3. 2

    principales necesidades de un tipo de retorno.

    clase Otra de las necesidades de un carácter semi-colon.

    clase Otra de las necesidades de sus miembros a ser público.

    También, los métodos no son considerados generalmente invisible; los métodos eran inaccesibles sin el acceso del público a la palabra clave.

    • Está bien para omitir una instrucción return en el main() de acuerdo con el estándar de c++, en cuyo caso se devuelve 0.
    • Divertido – yo estaba pensando en la declaración, como en: void main()….
    • IOW – me refiero a que el tipo había desaparecido de la decl, en lugar de un valor de retorno en el cuerpo de la principal.
  4. 1

    Me limpiaron el código para esto:

    template <int a>
    class Test {
    public:
        Test() {}
        int MyMethod1() { return a; }
    };
    
    template <int b>
    class Another : public Test<b>
    {
    public:
        Another() {}
        void MyMethod2() {
            MyMethod1();
        }
    };
    
    int main()
    {
        Another<5> a;
        a.MyMethod1();
        a.MyMethod2();
    }

    Y compilado con -fpermissive sin problemas (probablemente, usted puede resolver este problema).

    • Esto todavía tiene un error (no debería compilar en un estándar compatible con el compilador). Ver mi post de abajo.
    • MSVC a construir este tan largo como Deshabilitar las Extensiones del Lenguaje es off (valor predeterminado).
    • Eso es porque VC no apropiado de las dos de la fase de búsqueda. Los símbolos son, básicamente, sólo miró hacia arriba cuando la plantilla se crea una instancia. (Creo que hace un poco más, pero sólo apenas. Es increíble qué tipo de errores estúpidos pasar desapercibido sin dos de la fase de búsqueda hasta que alguien se crea una instancia de la plantilla. Si usted escribió la plantilla, que puede ser bastante embarazoso.)
  5. 0

    Yo creo que son sólo falta un público: en la parte superior de la Otra definición. Para preguntas como esta es generalmente útil para publicar los mensajes de error que usted está consiguiendo.

Dejar respuesta

Please enter your comment!
Please enter your name here