简体   繁体   English

错误:未在此范围内声明“朋友成员函数名称”

[英]Error: 'Friend Member Function Name' was not declared in this scope

I am in the process of moving all of my C++ Windows applications to Ubuntu Linux. 我正在将所有C ++ Windows应用程序移动到Ubuntu Linux。 This application runs fine on Visual Studio 2015 Community on Windows 7 OS. 此应用程序在Windows 7操作系统上的Visual Studio 2015社区中运行良好。 However, it gives an error when running in Code Blocks on Ubuntu Linux. 但是,在Ubuntu Linux上的代码块中运行时会出错。 I have replicated the error message I am getting using the following simple Person class. 我已经使用以下简单的Person类复制了我得到的错误消息。

Error Message: 'comparePersonAge' was not declared in this scope 错误消息:未在此范围内声明'comparePersonAge'

Person.h Person.h

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

#endif

main.cpp main.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;
}

On Windows machine, the output is: 32 67 93 as expected. 在Windows机器上,输出为: 32 67 93如预期的那样。 On Linux, the error message is as written above. 在Linux上,错误消息如上所述。

Note: Someone else name DJR discusses this issue in this post: Friend function not declared in this scope error . 注意:其他名称DJR在这篇文章中讨论了这个问题: 未在此范围内声明的朋友函数错误 However, his explanation is very vague I and don't follow his steps. 但是,他的解释非常模糊,不遵循他的步骤。

He writes: 他写:

Previous comment should have read: It is a bug on the the Linux side. 以前的评论应该是:这是Linux方面的一个错误。 The code should work as written. 代码应该按照书面形式工作。 I have code right now that compiles fine on the Windows side and when I move it to the Linux side I get the same error. 我现在有代码在Windows端编译很好,当我将它移动到Linux端时,我得到相同的错误。 Apparently the compiler that you are using on the Linux side does not see/use the friend declaration in the header file and hence gives this error. 显然,你在Linux端使用的编译器没有在头文件中看到/使用friend声明,因此给出了这个错误。 By simply moving the friend function's definition/implementation in the C++ file BEFORE that function's usage (eg: as might be used in function callback assignment), this resolved my issue and should resolve yours also. 通过在函数的用法之前简单地将友元函数的定义/实现移动到C ++文件中(例如:可能在函数回调赋值中使用),这解决了我的问题并且也应解决你的问题。

I don't know what he means by by moving the friend function's definition in the C++ file before the function's usage. 通过在函数使用之前移动友好函数在C ++文件中的定义,我不知道他的意思。 What does this mean precisely? 这究竟是什么意思?

The purpose of the friend keyword is to make an exception to the access rules ( protected and private ), giving a class or function access to members not otherwise allowed. friend关键字的目的是对访问规则( protectedprivate )进行例外处理,为不允许的成员提供类或函数访问权限。

So you can declare and define your comparePersonAge() function outside of your class declaration, and use the friend keyword inside the declaration, to give the function access to private members, age specifically. 因此,您可以在类声明之外声明和定义comparePersonAge()函数,并在声明中使用friend关键字,以使函数访问私有成员,具体使用age

Standard 7.3.1.2/3 : 标准7.3.1.2/3:

Every name first declared in a namespace is a member of that namespace. 首先在名称空间中声明的每个名称都是该名称空间的成员。 If a friend declaration in a non-local class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. 如果非本地类中的友元声明首先声明一个类或函数,那么友元类或函数是最内层封闭命名空间的成员。 The name of the friend is not found by unqualified lookup (3.4.1) or by qualified lookup (3.4.3) until a matching declaration is provided in that namespace scope (either before or after the class definition granting friendship). 在非命名查找(3.4.1)或限定查找(3.4.3)之前找不到朋友的名称,直到在该命名空间范围内提供匹配声明(在授予友谊的类定义之前或之后)。 If a friend function is called, its name may be found by the name lookup that considers functions from namespaces and classes associated with the types of the function arguments (3.4.2) . 如果调用了友元函数,则可以通过名称查找找到其名称,该名称查找考虑名称空间中的函数和与函数参数类型相关联的类(3.4.2) If the name in a friend declaration is neither qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace. 如果友元声明中的名称既不是限定语句也不是模板标识,并且声明是函数或详细类型说明符,则确定实体是否先前已声明的查找不应考虑最内层封闭命名空间之外的任何作用域。

Ok after little discussion with @Niall I realized that MSVC++ is wrong in this case, since ADL only happens in function call expression and since std::sort is being passed just name of function ie comparePersonAge , no function comparePersonAge should be found at the time of call to std::sort . 好的,在与@Niall讨论之后我意识到MSVC ++在这种情况下是错误的,因为ADL只发生在函数调用表达式中,并且因为std::sort只是传递函数的名称,即comparePersonAge ,所以当时不应该找到函数comparePersonAge调用std::sort Hence GCC and Clang are correct I think 因此,我认为GCC和Clang是正确的

A couple of points. 几点。

  1. There's no need to specify inline if it's defined within the class. 如果在类中定义了内inline则无需指定inline
  2. Although that declaration yields a friend function which is a member of the enclosing namespace of the class, until it's declared in that namespace explicitly, it's not available for regular lookup—though ADL is allowed. 尽管该声明产生了一个友元函数 ,该函数是该类的封闭命名空间的成员,但直到它在该命名空间中明确声明,它才可用于常规查找 - 尽管允许ADL。

So if you want to make it accessible via regular lookup, declare it in the enclosing namespace. 因此,如果您希望通过常规查找使其可访问,请在封闭的命名空间中声明它。

Demo 演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM