Home > Back-end >  Friend Function cannot access private members in C
Friend Function cannot access private members in C

Time:12-27

I have created class and trying to overload ostream operator using a friend function but my friend is not able access private members of functions. Please help me figure out the problem. I have created another friend function named doSomething() from here I can call private member but not from overloaded function. Please help me updating overloaded stream insertion function.

Class Header File:

#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 File:

#define _CRT_SECURE_NO_WARNINGS
#include "MyString.h"
#include <iostream>

using namespace std;

MyString::MyString() {
    length = 0;
    str = new char[1];
    str[length] = '\0';
}

MyString::MyString(const char* cString) {
    length=strlen(cString);
    str = new char[length 1];
    strcpy(str,cString);
    str[length] = '\0';
}

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] = '\0';
}

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;
}

Main 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;
}

CodePudding user response:

There are 2 problems with your code.

Mistake 1: You have not included iostream in MyString.h

Solution to mistake 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

Mistake 2: You have a missing & symbol while defining operator<< in main.cpp.

Solution to Mistake 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;
}

Additionally, i have added #inlcude <cstring> in MyString.cpp. So MyString.cpp now looks like:

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] = '\0';
}

MyString::MyString(const char* cString) {
    length=strlen(cString);
    str = new char[length 1];
    strcpy(str,cString);
    str[length] = '\0';
}

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] = '\0';
}

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;
}

The program now works(compiles) as can be verified here.

Additional Problem

You should not call the destructor(the way you're calling on the current object) from inside operator='s body.

You can solve this by using @PaulMcKenzie's suggestion in the comments of your original question.

const MyString& MyString::operator = (const MyString& Obj)
{  MyString temp(Obj); 
   std::swap(temp.str, str); 
   std::swap(temp.length, length); 
  
   return *this;
}

CodePudding user response:

your header file doesn't include and uses a "custom" type ostream, rather than std::ostream. In order to fix it, your header file should be

#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);
};

it's a result of using "using namespace std;" in you cpp file : the compiler allows you to not write std::ostream after it has read it. It will auto complete it. But as the type is not defined in your .h file and you don't refet to std::ostream, it will overload the function rather than using the "friend" one

  • Related