简体   繁体   English

朋友功能的单独声明

[英]Separate declaration for friend function

I am reading C++ Primer book. 我正在阅读C ++入门书籍。 It says: 它说:

A friend declaration only specifies access. 朋友声明仅指定访问权限。 It is not a general declaration of the function. 它不是函数的一般声明。 If we want users of the class to be able to call a friend function, then we must also declare the function separately from the friend declaration. 如果我们希望类的用户能够调用一个朋友函数,那么我们还必须将该函数与朋友声明分开声明。 To make a friend visible to users of the class, we usually declare each friend (outside the class) in the same header as the class itself. 为了使朋友对类的用户可见,我们通常在类本身的相同标头中声明每个朋友(类外部)。

Watch out for arrow in the code. 注意代码中的箭头。 Which asks my questions at those particular points in reference to above text. 参考上面的文字,我在那些特定的点问我的问题。

header.h header.h

#ifndef HEADER_H
#define HEADER_H

#include <iostream>
#include <string>

using namespace std;

class Husband{
    friend void change_salary(int changed_salary, Husband &ob);

public:
    Husband() {}
    Husband(unsigned new_salary) : salary{ new_salary } {}

private:
    int salary;

};

//void change_salary(int changed_salary, Husband &ob);  <----Code Compiles without even this declaration

#endif

main.cpp main.cpp中

#include "header.h"

void change_salary(int changed_salary, Husband &ob)
{
    cout << "salary increased by 1000";
    ob.salary = changed_salary;
}


int main()
{
    Husband hs1{ 3000 };

    change_salary(4000, hs1);  // <---- Able to use function without explicit declaration outside of class in header

    return 0; 
}

You don't need a prototype in the header file if you use the function in the same file it is declared in, after it was declared, which is what you did in main.cpp. 如果在声明函数后的声明文件中使用该函数,则在头文件中不需要原型,这就是在main.cpp中所做的事情。

Putting a prototype in the header file helps code in other files, or in the same file but higher up, find the function. 将原型放在头文件中有助于在其他文件中或在同一文件中(但在更高版本中)查找代码。 It is often a good practice to create a prototype in the header file to make the API clear to human readers. 在头文件中创建原型以使人类读者可以清楚了解API,通常是一种好习惯。 But in the case you have here, it is not strictly required to compile. 但是,在这种情况下,并非严格要求进行编译。

A friend function declaration is part of your your class design. 朋友函数声明是您的类设计的一部分。 Without a declaration of the function in your class header (or some included header) your design is incomplete (enforces a user to implement that function or opens the door for some user implementation or causing a one-definition-rule (ODR) violation). 如果没有在类标题(或某些包含的标题)中声明该函数,则您的设计是不完整的(迫使用户实现该功能或为某些用户实现打开门,或导致违反一个定义规则(ODR))。

You've provided the definition of change_salary before the definition of main() which uses it, so the function is always visible and there are no issues. 您已经在使用它的main()定义之前提供了change_salary的定义,因此该功能始终可见并且没有问题。 But let's say you move the definition below that of main() (or to a separate .cpp file). 但是,假设您将定义移至main()之下(或移至单独的.cpp文件)。

int main()
{
    Husband hs1{ 3000 };
    change_salary(4000, hs1);
}

void change_salary(int changed_salary, Husband &ob)
{
    cout << "salary increased by 1000";
    ob.salary = changed_salary;
}

The code will continue to compile even in this case because change_salary will be found by argument dependent name lookup (because the second argument is of type Husband& ). 即使在这种情况下,代码也将继续编译,因为change_salary将通过依赖参数的名称查找来找到(因为第二个参数的类型为Husband& )。

Now let's try to explicitly refer to change_salary by forming a pointer to it within main() . 现在,让我们尝试通过在main()形成指向change_salary的指针来明确引用它。

void (*p)(int, Husband&) = &change_salary;

This will fail to compile because ADL does not apply in this case, and the definition of change_salary is not visible to main() . 由于ADL在这种情况下不适用,并且change_salary的定义对于main()不可见,因此将无法编译

However, if you uncomment the declaration of change_salary within the header, the code will compile . 但是,如果取消注释标头中的change_salary声明,则代码将编译 This is presumably what the book meant when it said To make a friend visible to users of the class . 这可能是书中所说的“使班级用户认识朋友 ”的意思。

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

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