友元函数无法访问 C++ 中的私有成员
Friend Function cannot access private members in C++
我创建了 class 并尝试使用友元函数重载 ostream 运算符,但我的友元无法访问函数的私有成员。请帮我找出问题所在。我创建了另一个名为 doSomething() 的友元函数,我可以从这里调用私有成员,但不能从重载函数中调用。请帮我更新重载的流插入功能。
Class 头文件:
#pragma once
#ifndef MYSTRING_H
#define MYSTRING_H
class MyString
{
char* str;
int length;
public:
MyString();
MyString(const char*);
~MyString();
MyString (const MyString &Obj);
void Display() const;
int GetLength() const;
const MyString& operator = (const MyString&);
friend ostream& operator << (ostream &output,MyString&s);
friend void doSomething();
};
#endif
Class CPP 文件:
#define _CRT_SECURE_NO_WARNINGS
#include "MyString.h"
#include <iostream>
using namespace std;
MyString::MyString() {
length = 0;
str = new char[1];
str[length] = '[=11=]';
}
MyString::MyString(const char* cString) {
length=strlen(cString);
str = new char[length+1];
strcpy(str,cString);
str[length] = '[=11=]';
}
MyString::~MyString() {
delete[] str;
str = nullptr;
length = 0;
}
MyString::MyString(const MyString& Obj) {
length = Obj.length;
str = new char[length+1];
strcpy(str, Obj.str);
str[length] = '[=11=]';
}
void MyString::Display() const {
cout << str << endl;
}
int MyString::GetLength() const {
return length;
}
const MyString& MyString::operator = (const MyString& Obj) {
this->~MyString();
length = Obj.length;
str = new char[length + 1];
strcpy(str, Obj.str);
return *this;
}
主要 CPP:
#define _CRT_SECURE_NO_WARNINGS
#include "MyString.h"
#include <iostream>
using namespace std;
ostream &operator << (ostream& output, MyString s) {
output << s.length;
return output;
}
void doSomething() {
MyString s;
s.length;
}
int main() {
return 0;
}
您的头文件不包含并使用“自定义”类型的 ostream,而不是 std::ostream。为了修复它,你的头文件应该是
#pragma once
#include <iostream>
class MyString
{
char* str;
int length;
public:
MyString();
MyString(const char*);
~MyString();
MyString (const MyString &Obj);
void Display() const;
int GetLength() const;
const MyString& operator = (const MyString&);
friend std::ostream& operator << (std::ostream &output,MyString&s);
};
这是使用“using namespace std;”的结果在您的 cpp 文件中:编译器允许您在读取 std::ostream 后不写入它。它会自动完成它。但是由于该类型未在您的 .h 文件中定义并且您没有引用 std::ostream,它会重载函数而不是使用“朋友”
您的代码存在 2 个问题。
错误 1:您没有在 MyString.h
中包含 iostream
错误1的解决方法
MyString.h
#pragma once
#ifndef MYSTRING_H
#define MYSTRING_H
#include <iostream> //ADDED THIS
class MyString
{
char* str;
int length;
public:
MyString();
MyString(const char*);
~MyString();
MyString (const MyString &Obj);
void Display() const;
int GetLength() const;
const MyString& operator = (const MyString&);
friend std::ostream& operator << (std::ostream &output,MyString&s); //ADDED STD:: here
friend void doSomething();
};
#endif
错误 2:在 main.cpp 中定义 operator<<
时缺少 &
符号。
错误 2 的解决方法
main.cpp
#define _CRT_SECURE_NO_WARNINGS
#include "MyString.h"
#include <iostream>
using namespace std;
ostream &operator << (ostream& output, MyString &s) {//ADDED & HERE
output << s.length;
return output;
}
void doSomething() {
MyString s;
s.length;
}
int main() {
return 0;
}
此外,我在MyString.cpp中添加了#inlcude <cstring>
。所以 MyString.cpp 现在看起来像:
MyString.cpp
#define _CRT_SECURE_NO_WARNINGS
#include "MyString.h"
#include <iostream>
#include <cstring>
using namespace std;
MyString::MyString() {
length = 0;
str = new char[1];
str[length] = '[=12=]';
}
MyString::MyString(const char* cString) {
length=strlen(cString);
str = new char[length+1];
strcpy(str,cString);
str[length] = '[=12=]';
}
MyString::~MyString() {
delete[] str;
str = nullptr;
length = 0;
}
MyString::MyString(const MyString& Obj) {
length = Obj.length;
str = new char[length+1];
strcpy(str, Obj.str);
str[length] = '[=12=]';
}
void MyString::Display() const {
cout << str << endl;
}
int MyString::GetLength() const {
return length;
}
const MyString& MyString::operator = (const MyString& Obj) {
this->~MyString();
length = Obj.length;
str = new char[length + 1];
strcpy(str, Obj.str);
return *this;
}
程序现在可以运行(编译),可以验证here。
其他问题
您不应该从 operator=
的主体内部调用析构函数(调用当前对象的方式)。
您可以使用 @PaulMcKenzie 在您原始问题的评论中提出的建议来解决这个问题。
const MyString& MyString::operator = (const MyString& Obj)
{ MyString temp(Obj);
std::swap(temp.str, str);
std::swap(temp.length, length);
return *this;
}
我创建了 class 并尝试使用友元函数重载 ostream 运算符,但我的友元无法访问函数的私有成员。请帮我找出问题所在。我创建了另一个名为 doSomething() 的友元函数,我可以从这里调用私有成员,但不能从重载函数中调用。请帮我更新重载的流插入功能。
Class 头文件:
#pragma once
#ifndef MYSTRING_H
#define MYSTRING_H
class MyString
{
char* str;
int length;
public:
MyString();
MyString(const char*);
~MyString();
MyString (const MyString &Obj);
void Display() const;
int GetLength() const;
const MyString& operator = (const MyString&);
friend ostream& operator << (ostream &output,MyString&s);
friend void doSomething();
};
#endif
Class CPP 文件:
#define _CRT_SECURE_NO_WARNINGS
#include "MyString.h"
#include <iostream>
using namespace std;
MyString::MyString() {
length = 0;
str = new char[1];
str[length] = '[=11=]';
}
MyString::MyString(const char* cString) {
length=strlen(cString);
str = new char[length+1];
strcpy(str,cString);
str[length] = '[=11=]';
}
MyString::~MyString() {
delete[] str;
str = nullptr;
length = 0;
}
MyString::MyString(const MyString& Obj) {
length = Obj.length;
str = new char[length+1];
strcpy(str, Obj.str);
str[length] = '[=11=]';
}
void MyString::Display() const {
cout << str << endl;
}
int MyString::GetLength() const {
return length;
}
const MyString& MyString::operator = (const MyString& Obj) {
this->~MyString();
length = Obj.length;
str = new char[length + 1];
strcpy(str, Obj.str);
return *this;
}
主要 CPP:
#define _CRT_SECURE_NO_WARNINGS
#include "MyString.h"
#include <iostream>
using namespace std;
ostream &operator << (ostream& output, MyString s) {
output << s.length;
return output;
}
void doSomething() {
MyString s;
s.length;
}
int main() {
return 0;
}
您的头文件不包含并使用“自定义”类型的 ostream,而不是 std::ostream。为了修复它,你的头文件应该是
#pragma once
#include <iostream>
class MyString
{
char* str;
int length;
public:
MyString();
MyString(const char*);
~MyString();
MyString (const MyString &Obj);
void Display() const;
int GetLength() const;
const MyString& operator = (const MyString&);
friend std::ostream& operator << (std::ostream &output,MyString&s);
};
这是使用“using namespace std;”的结果在您的 cpp 文件中:编译器允许您在读取 std::ostream 后不写入它。它会自动完成它。但是由于该类型未在您的 .h 文件中定义并且您没有引用 std::ostream,它会重载函数而不是使用“朋友”
您的代码存在 2 个问题。
错误 1:您没有在 MyString.h
iostream
错误1的解决方法
MyString.h
#pragma once
#ifndef MYSTRING_H
#define MYSTRING_H
#include <iostream> //ADDED THIS
class MyString
{
char* str;
int length;
public:
MyString();
MyString(const char*);
~MyString();
MyString (const MyString &Obj);
void Display() const;
int GetLength() const;
const MyString& operator = (const MyString&);
friend std::ostream& operator << (std::ostream &output,MyString&s); //ADDED STD:: here
friend void doSomething();
};
#endif
错误 2:在 main.cpp 中定义 operator<<
时缺少 &
符号。
错误 2 的解决方法
main.cpp
#define _CRT_SECURE_NO_WARNINGS
#include "MyString.h"
#include <iostream>
using namespace std;
ostream &operator << (ostream& output, MyString &s) {//ADDED & HERE
output << s.length;
return output;
}
void doSomething() {
MyString s;
s.length;
}
int main() {
return 0;
}
此外,我在MyString.cpp中添加了#inlcude <cstring>
。所以 MyString.cpp 现在看起来像:
MyString.cpp
#define _CRT_SECURE_NO_WARNINGS
#include "MyString.h"
#include <iostream>
#include <cstring>
using namespace std;
MyString::MyString() {
length = 0;
str = new char[1];
str[length] = '[=12=]';
}
MyString::MyString(const char* cString) {
length=strlen(cString);
str = new char[length+1];
strcpy(str,cString);
str[length] = '[=12=]';
}
MyString::~MyString() {
delete[] str;
str = nullptr;
length = 0;
}
MyString::MyString(const MyString& Obj) {
length = Obj.length;
str = new char[length+1];
strcpy(str, Obj.str);
str[length] = '[=12=]';
}
void MyString::Display() const {
cout << str << endl;
}
int MyString::GetLength() const {
return length;
}
const MyString& MyString::operator = (const MyString& Obj) {
this->~MyString();
length = Obj.length;
str = new char[length + 1];
strcpy(str, Obj.str);
return *this;
}
程序现在可以运行(编译),可以验证here。
其他问题
您不应该从 operator=
的主体内部调用析构函数(调用当前对象的方式)。
您可以使用 @PaulMcKenzie 在您原始问题的评论中提出的建议来解决这个问题。
const MyString& MyString::operator = (const MyString& Obj)
{ MyString temp(Obj);
std::swap(temp.str, str);
std::swap(temp.length, length);
return *this;
}