Estoy en el proceso de mover todas mis aplicaciones de Windows C++ a Ubuntu Linux. Esta aplicación funciona bien en Visual Studio 2015 Community en el sistema operativo Windows 7. Sin embargo, da un error cuando se ejecuta en Code Blocks en Ubuntu Linux. He replicado el mensaje de error que recibo usando la siguiente clase de Person simple.
Mensaje de error: 'comparePersonAge' no se declaró en este ámbito
#ifndef Person_h #define Person_h #include <string> class Person { private: int age; std::string name; public: Person(int a, std::string n) : age(a), name(n) {} int getAge() { return age; } std::string getName() { return name; } inline friend bool comparePersonAge(const Person& p1, const Person& p2) { return p1.age < p2.age; } }; #endifprincipal.cpp
#include <iostream> #include <algorithm> #include <vector> #include "Person.h" int main() { Person p1(93, "harold"); Person p2(32, "james"); Person p3(67, "tracey"); std::vector<Person> v; v.push_back(p1); v.push_back(p2); v.push_back(p3); std::sort(v.begin(), v.end(), comparePersonAge); std::cout << v[0].getAge() << " " << v[1].getAge() << " " << v[2].getAge() << std::endl; } En una máquina con Windows, el resultado es: 32 67 93 como se esperaba. En Linux, el mensaje de error es como está escrito arriba.
Nota: Alguien más llamado DJR analiza este problema en esta publicación: Función de amigo no declarada en este error de alcance . Sin embargo, su explicación es muy vaga y no sigo sus pasos.
El escribe:
El comentario anterior debería haber dicho: Es un error en el lado de Linux. El código debería funcionar como está escrito. Tengo un código en este momento que se compila bien en el lado de Windows y cuando lo muevo al lado de Linux obtengo el mismo error. Aparentemente, el compilador que está usando en el lado de Linux no ve/usa la declaración de amigo en el archivo de encabezado y, por lo tanto, da este error. Simplemente moviendo la definición/implementación de la función de amigo en el archivo C++ ANTES del uso de esa función (por ejemplo, como podría usarse en la asignación de devolución de llamada de función), esto resolvió mi problema y debería resolver el suyo también.
No sé qué quiere decir con mover la definición de la función amigo en el archivo C++ antes del uso de la función. ¿Qué significa esto precisamente?
El propósito de la palabra clave friend es hacer una excepción a las reglas de acceso ( protected y private ), otorgando acceso a una clase o función a los miembros que de otro modo no estarían permitidos.
Por lo tanto, puede declarar y definir su función comparePersonAge() fuera de su declaración de clase, y usar la palabra clave friend dentro de la declaración, para dar acceso a la función a miembros privados, específicamente a la age .
Estándar 7.3.1.2/3:
Cada nombre declarado por primera vez en un espacio de nombres es un miembro de ese espacio de nombres. Si una declaración de amigo en una clase no local declara primero una clase o función, la clase o función amiga es miembro del espacio de nombres adjunto más interno. El nombre del amigo no se encuentra mediante una búsqueda no calificada (3.4.1) o una búsqueda calificada (3.4.3) hasta que se proporciona una declaración coincidente en ese ámbito de espacio de nombres (ya sea antes o después de la definición de clase que otorga amistad). Si se llama a una función amiga, su nombre se puede encontrar mediante la búsqueda de nombres que considera funciones de espacios de nombres y clases asociadas con los tipos de argumentos de la función (3.4.2) . Si el nombre en una declaración de amigo no está calificado ni es una identificación de plantilla y la declaración es una función o un especificador de tipo elaborado, la búsqueda para determinar si la entidad ha sido declarada previamente no considerará ningún ámbito fuera del espacio de nombres más interno. .
Ok, después de una pequeña discusión con @Niall, me di cuenta de que MSVC ++ está mal en este caso, ya que ADL solo ocurre en la expresión de llamada de función y dado que std::sort se pasa solo el nombre de la función, es decir, comparePersonAge , no se debe encontrar ninguna función comparePersonAge en ese momento de llamada a std::sort . Por lo tanto, GCC y Clang son correctos, creo.
Un par de puntos.
inline si está definido dentro de la clase.Entonces, si desea que sea accesible a través de una búsqueda regular, declárelo en el espacio de nombres adjunto.