在做一些代码练习时,我得到了一些错误
student.h文件
#pragma once
class Student {
public:
Student() = default;
Student(int id, const char* name, int score);
Student(const Student& s);
Student(Student&& other);
Student& operator=(Student&& other);
virtual ~Student();
**friend std::ostream & operator<<(std::ostream & os, const Student & rhs);**
void print();
private:
int mId;
char* mName;
int mScore;
size_t mSize;
};
student.cpp文件
#include "student.h"
#include <iostream>
#include <string>
... //bunch of constructors, override...
std::ostream & operator<<(std::ostream& os, const Student & rhs)
{
os << rhs.mId << rhs.mName << rhs.mScore ; // Compile Error: Cannot Access Student Member(rhs.mId, rhs.mName...)
return os;
}
我得到的错误是我不能访问Student类成员,尽管我在Student .h中声明了它为友函数
奇怪的是,如果我像这样在student.cpp
文件中声明#include<iostream>
语句,它就编译成功了
#include <iostream> //change position <iostream> and "student.h"
#include <string>
#include "student.h"
... //bunch of constructors, override...
std::ostream & operator<<(std::ostream& os, const Student & rhs)
{
os << rhs.mId << rhs.mName << rhs.mScore ; //Compile successfully
return os;
}
那么,为什么#include语句序列很重要呢?我想#include语句只是复制粘贴到我的CPP文件。
并且当我将#include<iostream>
声明到student.h,
时也编译成功。所以当我包含一些#include的东西最好的情况是声明它的头文件?
你能给我一些建议吗?
我在Visual Studio 2019中编译我的程序。
在student.h中添加iosfwd
的include:
#pragma once
#include <iosfwd>
class Student ...
这将确保std::ostream符号的正确解析,并将您定义的ostream操作符识别为您声明为友元的操作符。
iosfwd头文件包含iostream头文件中符号的前向声明,它是为这个场景定义的。
在c++中,我们必须在使用任何东西之前声明它。
所以你的问题是你没有声明std::ostream
,但你在student.h中使用了它。
一个合适的解是在student.h开头的#include <iostream>
,#pragma once
下面。
你也可以把这些放在class Stduent
:
namespace std
{
class ostream;
}
这叫做正向声明。