将 .h(库)文件中的函数声明为类的友元
我正在为产品列表编写一个简单的类,我需要重载提取>>运算符和插入 <<操作符写入文件并从文件
Student_projectV1/list.h
#ifndef STUDENT_PROJECTV1_LIST
#define STUDENT_PROJECTV1_LIST
#include <fstream>
namespace list {
class list {
private:
string name;
int price;
short quantity;
public:
ofstream ofs;
ifstream ifs;
// file_mutators
void set_created_file () noexcept(false) ;
void set_readable_file ();
// constructors
list() noexcept ( noexcept ( set_created_file() ) ) ;
list ( string , int , short ) noexcept(false) ;
list ( class list &) noexcept ( noexcept ( set_created_file() ) ) ;
// initialization to cover after construction of an obj
void initialize ( string , int , short ) noexcept(false) ;
// mutators
void set_name ( string ) noexcept(false);
void set_price ( int ) noexcept(false) ;
void set_quantity ( short ) noexcept(false) ;
// accessors
string get_name ( ) const noexcept;
int get_price () const noexcept;
int get_quantity () const noexcept;
// Enqueries
bool check_created_file () noexcept;
bool check_opened_file();
// destructor
~list();
// friend global functions
// overloaded operators
friend ofstream & friend_global_funcs :: operator << ( ofstream & , class list::list &) ;
friend ifstream & friend_global_funcs :: operator >> ( ifstream & , class list::list &) ;
};
}
#endif
中读取现在我计划将这两个重载函数的定义放在命名空间friend_global_funcs.h内的另一个 friend_global_funcs.h
文件
friend ofstream & friend_global_funcs :: operator << ( ofstream & , class list::list &) ;
friend ifstream & friend_global_funcs :: operator >> ( ifstream & , class list::list &) ;
中
//
// Created by solo-l-ub on 2/27/22.
//
#ifndef STUDENT_PROJECTV1_FRIEND_GLOBAL_FUNCS_H
#define STUDENT_PROJECTV1_FRIEND_GLOBAL_FUNCS_H
namespace friend_global_funcs {
ofstream & operator<< (ofstream &ofs, class list::list &l) {
if (!l.check_created_file())
throw new file_missing::file_missing(
"can not write info to file something wrong with acquiring file in constructor of obj \n");
ofs << l.name() << "\t" << l.price << "\t" << l.quantity << "\n";
return ofs;
}
ifstream & operator>>(ifstream &ifs, list :: list &l) {
l.set_readable_file();
if (!l.check_opened_file())
throw new file_missing::file_missing(
"can't retrieve data cuz file is not associated with obj currently I'm in operated >> overloaded fuc \n");
ifs >> l.name >> l.price >> l.quantity;
return ifs;
}
}
#endif //STUDENT_PROJECTV1_FRIEND_GLOBAL_FUNCS_H
我的场景在 main.cpp
文件中包含文件的顺序我首先包含类 list.h
,然后包含 friend_global_funcs.h 文件
main.cpp
#include <iostream>
using namespace std;
// using namespaces
// classes
#include "file_missing.h"
#include "empty.h"
#include "list.h"
// libraries
#include "friend_global_funcs.h"
int main() {
//////////////////////////////////////
return 0;
}
现在,当我尝试使用 g++ 在终端中编译
g++ main.cpp -o out
时,我收到错误,即 list.h
中的重载函数未声明,即使我已使用范围解析运算符来告诉编译器确切的位置寻找函数 friend_global_funcs::operator <<
g++ 终端错误
In file included from main.cpp:33:
list.h:64:31: error: ‘friend_global_funcs’ has not been declared
64 | friend ofstream & friend_global_funcs :: operator << ( ofstream & , class list::list &) ;
现在我已经上传了我的项目,这是一个非常非常轻的项目,只是为了练习从类内部到 github 的文件写入和读取 如果您想看一下它并指导我使用在类
github src 中的另一个 .h 文件中定义的函数的友谊的正确顺序 https://github.com/moji2013/student_projectV1.git
I’m writing a simple class for list of products and there I need to overload both extraction >> operator and insertion << operator to write into file and read from file
student_projectV1/list.h
#ifndef STUDENT_PROJECTV1_LIST
#define STUDENT_PROJECTV1_LIST
#include <fstream>
namespace list {
class list {
private:
string name;
int price;
short quantity;
public:
ofstream ofs;
ifstream ifs;
// file_mutators
void set_created_file () noexcept(false) ;
void set_readable_file ();
// constructors
list() noexcept ( noexcept ( set_created_file() ) ) ;
list ( string , int , short ) noexcept(false) ;
list ( class list &) noexcept ( noexcept ( set_created_file() ) ) ;
// initialization to cover after construction of an obj
void initialize ( string , int , short ) noexcept(false) ;
// mutators
void set_name ( string ) noexcept(false);
void set_price ( int ) noexcept(false) ;
void set_quantity ( short ) noexcept(false) ;
// accessors
string get_name ( ) const noexcept;
int get_price () const noexcept;
int get_quantity () const noexcept;
// Enqueries
bool check_created_file () noexcept;
bool check_opened_file();
// destructor
~list();
// friend global functions
// overloaded operators
friend ofstream & friend_global_funcs :: operator << ( ofstream & , class list::list &) ;
friend ifstream & friend_global_funcs :: operator >> ( ifstream & , class list::list &) ;
};
}
#endif
now I plan to place the definition of these two overloaded functions in another friend_global_funcs.h
file inside a namespace
friend ofstream & friend_global_funcs :: operator << ( ofstream & , class list::list &) ;
friend ifstream & friend_global_funcs :: operator >> ( ifstream & , class list::list &) ;
friend_global_funcs.h
//
// Created by solo-l-ub on 2/27/22.
//
#ifndef STUDENT_PROJECTV1_FRIEND_GLOBAL_FUNCS_H
#define STUDENT_PROJECTV1_FRIEND_GLOBAL_FUNCS_H
namespace friend_global_funcs {
ofstream & operator<< (ofstream &ofs, class list::list &l) {
if (!l.check_created_file())
throw new file_missing::file_missing(
"can not write info to file something wrong with acquiring file in constructor of obj \n");
ofs << l.name() << "\t" << l.price << "\t" << l.quantity << "\n";
return ofs;
}
ifstream & operator>>(ifstream &ifs, list :: list &l) {
l.set_readable_file();
if (!l.check_opened_file())
throw new file_missing::file_missing(
"can't retrieve data cuz file is not associated with obj currently I'm in operated >> overloaded fuc \n");
ifs >> l.name >> l.price >> l.quantity;
return ifs;
}
}
#endif //STUDENT_PROJECTV1_FRIEND_GLOBAL_FUNCS_H
now My scenario of the order of including files in main.cpp
file I’ve included first the class list.h
and then the friend_global_funcs.h file
main.cpp
#include <iostream>
using namespace std;
// using namespaces
// classes
#include "file_missing.h"
#include "empty.h"
#include "list.h"
// libraries
#include "friend_global_funcs.h"
int main() {
//////////////////////////////////////
return 0;
}
now when I try to compile in terminal using g++
g++ main.cpp -o out
I get the error that overloaded functions in list.h
are not declared even though I’ve used the scope resolution operator to tell compiler to exactly where to look for the function friend_global_funcs :: operator <<
g++ terminal error
In file included from main.cpp:33:
list.h:64:31: error: ‘friend_global_funcs’ has not been declared
64 | friend ofstream & friend_global_funcs :: operator << ( ofstream & , class list::list &) ;
now I’ve uploaded my project which is a very very light project just to practice writing and reading to files from inside classes to github
in case you want to take a look at it and guide me the proper sequence to use the friendship of a function which is defined in another .h file in a class
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题是,在当前的
list.h
中,您有 2 个使用范围解析运算符的友元声明::
引用命名空间friend_global_funcs
内的operator<<
和operator>>
。在这些友元声明时,编译器不知道命名空间friend_global_funcs
。因此,要解决这个问题,您需要告诉编译器有一个名为
friend_global_funcs
的命名空间,其中包含operator<<
和的声明>operator>>
如下所示(工作中演示):list.h
list.cpp
friend_global_funcs.cpp
工作演示
我所做的一些更改包括:
friend_global_funcs
list.h
。此命名空间包含operator<<
和operator>>
的前向声明。list.h
和friend_global_funcs.cpp
内重载的operator<<
的第二个参数添加了一个低级常量。friend_global_funcs.h
的名称更改为friend_global.funcs.cpp
,因为它包含实现。PS:我花了大约 30 分钟从您给定的 github 存储库创建一个工作示例。您的程序中可能存在其他我尚未检查的逻辑错误,因为存储库相当大。我专注于手头的问题(即重载
operator<<
和operator>>
)。The problem is that in your current
list.h
, you have 2 friend declarations that uses the scope resolution operator::
to refer tooperator<<
andoperator>>
inside the namespacefriend_global_funcs
. And at the point of these friend declaration the compiler doesn't know about the namespacefriend_global_funcs
.So to solve this you need to tell the compiler that there is a namespace called
friend_global_funcs
that has the declarations foroperator<<
andoperator>>
as shown below(Working Demo):list.h
list.cpp
friend_global_funcs.cpp
Working Demo
Some of the changes that i made include:
friend_global_funcs
inside filelist.h
. This namespace contains the forward declarations for theoperator<<
andoperator>>
.operator<<
inside fileslist.h
andfriend_global_funcs.cpp
.friend_global_funcs.h
tofriend_global.funcs.cpp
since it contains implementation.PS: It took me around 30 minutes to create a working example out of your given github repo. There may be other logical errors in your program that i haven't checked because the repo is quite big. I was focusing on the problem at hand(which was to overload
operator<<
andoperator>>
).list.h 包含friend_global_funcs.h,friend_global_funcs.h 包含list.h。这是行不通的。 A 不能在 B 之前,而 B 也在 A 之前。标头防护可以防止无限递归,但最终会导致一个标头位于第一个,因此没有它所依赖的声明。
正确的解决方案是遵循以下顺序:
list::list
friend_global_funcs::operator<<
和friend_global_funcs::operator>>
list::list
friend_global_funcs::operator<<
并friend_global_funcs::operator>>
PS 如果您在头文件中定义函数,那么您应该将该函数设为内联,这样您就不会因包含非内联定义而意外违反定义规则分成多个翻译单元。您还应该考虑为什么要在头文件中定义函数。
list.h includes friend_global_funcs.h and friend_global_funcs.h includes list.h. This cannot work. A cannot be before B while B is also before A. The header guards prevent infinite recursion, but you end up with one header being first, and thus not having the declartions that it depends on.
A correct solution is to follow this order:
list::list
friend_global_funcs::operator<<
andfriend_global_funcs::operator>>
list::list
friend_global_funcs::operator<<
andfriend_global_funcs::operator>>
P.S. If you define a function in a header file, then you should make that function inline so that you don't accidentally violate one definition rule by including the non-inline definition into multiple translation units. You should also think about why you want to define the functions within a header file.