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