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

时间:2016-02-17 17:06:51

标签: c++ linux oop codeblocks friend

我正在将所有C ++ Windows应用程序移动到Ubuntu Linux。此应用程序在Windows 7操作系统上的Visual Studio 2015社区上运行良好。但是,在Ubuntu Linux上的代码块中运行时会出错。我使用以下简单的Person类复制了我收到的错误消息。

  

错误消息:未在此范围内声明'comparePersonAge'

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

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

在Windows计算机上,输出为:32 67 93按预期方式。在Linux上,错误消息如上所示。

注意:其他人的名字DJR在这篇文章中讨论了这个问题:Friend function not declared in this scope error。 但是,他的解释非常模糊,不遵循他的步骤。

他写道:

  

以前的评论应该是:这是Linux方面的一个错误。代码应该按照书面形式工作。我现在有代码在Windows端编译很好,当我将它移动到Linux端时,我得到相同的错误。显然,你在Linux端使用的编译器没有在头文件中看到/使用friend声明,因此给出了这个错误。通过简单地在C ++文件中移动友元函数的定义/实现BEFORE函数的用法(例如:可能在函数回调赋值中使用),这解决了我的问题并且也应解决你的问题。

我不知道在函数使用之前在C ++文件中移动友元函数的定义意味着什么。这究竟意味着什么?

3 个答案:

答案 0 :(得分:1)

friend关键字的目的是对访问规则(protectedprivate)进行例外处理,为不允许的成员提供类或函数访问权。

因此,您可以在类声明之外声明和定义comparePersonAge()函数,并在声明中使用friend关键字,以使函数能够访问私有成员,age具体

答案 1 :(得分:1)

标准7.3.1.2/3:

  

首先在名称空间中声明的每个名称都是其中的一员   命名空间。 如果非本地类中的朋友声明首先声明   朋友类或函数所属的类或函数   最里面的封闭命名空间。找不到朋友的名字   非限定查找(3.4.1)或通过限定查找(3.4.3)直到a   在该命名空间范围内提供匹配声明(或者   在授予友谊的类定义之前或之后)。如果是朋友   函数被调用,其名称可以通过名称查找找到   考虑来自名称空间和与之关联的类的函数   函数参数的类型(3.4.2)。如果是朋友的名字   声明既不是合格的,也不是模板ID和声明   是一个函数或一个精心设计的类型说明符,用于确定的查找   该实体是否先前已被宣布不得考虑任何实体   最内层封闭命名空间之外的范围。

好的,在与@Niall讨论之后我意识到MSVC ++在这种情况下是错误的,因为ADL只发生在函数调用表达式中,并且因为std::sort只传递函数名称即comparePersonAge,所以没有在致电comparePersonAge时应找到函数std::sort。因此,我认为GCC和Clang是正确的

答案 2 :(得分:0)

有几点。

  1. 如果在课程中定义inline,则无需指定 $parent = array( array(//$parent[0] "a-key", "b-key" => array( array("1", "2", "3"), //b-key[0] array("4", "5", "6")) //b-key[1] , "c-key"), array(//$parent[1] "a-key", "b-key" => array(array("7", "8", "9"), //b-key[0] array("10", "16", //b-key[1] "12" => array(array("13"), //12[0] array("14"))), //12[1] array("15", "16" => array(), "17")) //b-key[2] , "c-key"), array(//$parent[2] "a-key", "b-key" => array(array("7", "8", "9"), //b-key[0] array("10", "16", //b-key[1] "12" => array(array("13"), //12[0] array("14"))), //12[1] array("15", "16" => array(), "17")) //b-key[2] , "c-key") );
  2. 虽然该声明产生friend function,它是该类封闭命名空间的成员,但在它明确地声明在该命名空间之前,它不是可用于常规查找 - 但允许ADL。
  3. 因此,如果您想通过常规查找使其可访问,请在封闭的命名空间中声明它。

    Demo