友元函数无法访问 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;
}