c++ error : (private data member) was not declared in this scope - c++

Say I have a class like so:
class Ingredient
{
public:
friend istream& operator>>(istream& in, Ingredient& target);
friend ostream& operator<<(ostream& out, Ingredient& data);
private:
Measure myMeas;
MyString myIng;
};
In this overloaded friend function, I'm trying to set the value of myIng
istream& operator>>(istream& in, Ingredient& target)
{
myIng = MyString("hello");
}
In my mind, this should work because I'm setting the value of a private data member of the class Ingredient in a friend function and the friend function should have access to all the private data members right?
But I get this error: ‘myIng’ was not declared in this scope
Any idea on why this is happening?

Because you need to be be explicit that you are accessing a member of the target parameter, not a local or global variable:
istream& operator>>(istream& in, Ingredient& target)
{
target.myIng = MyString("hello"); // accessing a member of target!
return in; // to allow chaining
}
The above will work exactly because the operator is a friend of Ingredient as you mention. Try removing the friendship and you will see that accessing private members will no longer be possible.
Also, as Joe comments: stream operators should return their stream parameter so that you can chain them.

In that scope, there is nothing called myIng. The error is pretty clear on that. Its Ingredient& target who has a myIng member, so you should write:
target.myIng = MyString("hello");

Related

std::ostream : class is inaccesible [C++]

I am getting this error in my implementation:
struct bookdatabase::Bookdatabase::Book
class "bookdatabase::BookDatabase::Book" is inaccessible
None of the following solutions solved my problem:
std::basic_ostream is inaccessible in C++
cannot access private members in friend ostream
My ostream and istream friend function can't access private class members
member of class inaccessible
Inaccessible Members ?
Here's a picture of what visual studio has issue with in the .cpp file.
Here's a picture of the declaration in the header file.
Database.h
#include <string>
#include <vector>
#ifndef BOOKDATABASE_H
#define BOOKDATABASE_H
namespace bookdatabase {
class BookDatabase {
private:
struct Book {
private:
std::string authorFirstName, authorLastName, authorFullName, bookTitle, pubDate;
public:
Book(const std::string &authFirst, const std::string &authLast, const std::string &title, const std::string &date);
std::string getAuthor() const;
std::string getBookTitle() const;
std::string getPubDate() const;
bool operator < (const Book &rhs) const;
friend std::ostream& operator << (std::ostream& out, const bookdatabase::BookDatabase::Book& book);
};
void sortBooks();
std::vector<Book>::iterator search(const std::string &title);
public:
BookDatabase();
void printBookList();
std::vector<Book> getDatabase() const;
void removeBook(const std::string &title);
void addBook(const std::string &authFirst, const std::string &authLast, const std::string &title, const std::string &date);
private:
std::vector<Book> database;
};
}
#endif // BOOKDATABASE_H
Database.cpp
std::ostream & bookdatabase::operator<<(std::ostream & out, const bookdatabase::BookDatabase::Book & book) {
out << authorFullName << ". " << bookTitle << ". " << pubDate;
return out;
}
Am I having this issue because the Book class is a nested class?
Alright, I seem to have discovered two things here which might be the problem you're having, one of which might be a bug in Visual Studio.
1. First of all, the thing which is not a bug
user0042, in his response to your post is right, operator<< being declared as friend in the struct Book results in the operator<< only being able to access private members of Book. But it cannot access Book itself, because Book is a private member of the enclosing BookDatabase class. Therefore you have to move the friend declaration to be outside Book and in BookDatabase.
Once you do that, operator<< can now access the private data member Book of BookDatabase. Note however that this does not give permission to operator<< to access the private data members of Book itself, namely authorFirstName, authorLastName, authorFullName, bookTitle, pubDate
2A. Now for the (what I believe to be) VS2017 scope operator bug
Let's say you have moved the friend declaration to BookDatabase, you still have to define the implementation in a specific way. The following two pieces of code should be equivalent ways to define the function in a Database.cpp file, but one of them doesn't work in VS2017 15.4.5.
It's ok to do
namespace bookdatabase {
ostream& operator<<(ostream& out, const bookdatabase::BookDatabase::Book& book) {
}
} // OK
But not ok to do
ostream& bookdatabase::operator<<(ostream& out, const bookdatabase::BookDatabase::Book& book) {
} // Visual Studio cannot access book
There seems to be an issue with Visual Studio's :: operator being able to obtain the friend property of a function.
So to answer your question: if you want your << operator overload to work you need to use the first method to define it in the .cpp implementation file.
2B. In fact I wrote a simple test program to show the VS2017 friend and :: bug
namespace my_namespace {
class Test {
private:
struct Nested {};
public:
friend void func(Test::Nested&);
};
void func(Test::Nested&);
}
// DOES NOT COMPILE in VS2017 15.4.5, OK in GCC 6.3 and Clang 3.8.0
// VS2017 says Nested is inaccessible
void my_namespace::func(my_namespace::Test::Nested&) {
}
But using namespace and brackets works
namespace my_namespace {
class Test {
private:
struct Nested {};
public:
friend void func(Test::Nested&);
};
void func(Test::Nested&);
}
// changed to namespace + brackets,
// COMPILES in VS2017 15.4.5, GCC 6.3 and Clang 3.8.0
namespace my_namespace {
void func(my_namespace::Test::Nested&) {
}
}
Can someone please independently verify this?
I also posted a bug report on the Microsoft Developer Community
My answer for most operator << woes is to declare a member print() method that does the hard work and call it from operator <<.
Usually I am happy for the print method to be public, and get rid of all the friend nastiness.

Friend functions not locating private members

Please do not vote this down or mark this question as a duplicate for all of the answers that I have seen in other questions have not worked for me.
I created a class called contact that stores information about contacts. I was trying to implement an operator<< to output all information, so I had to make it a friend function. The problem with this is that I am unable to access any of the class's member functions. My code is as follows:
contact.h:
class contact {
long id;
string first;
string middle;
string last;
string company;
string home;
string office;
string email;
string mobile;
string street;
string city;
string state;
long zip;
string country;
vector<contact> affiliates;
public:
// output and input
friend ostream &operator<<(ostream &, const contact &);
};
contact.cpp:
...
ostream &operator<<(ostream &os, contact &rec) {
print(os, rec.id);
return os;
}
...
As you see, the function prototype is exactly the same, and I am not enclosing the class inside a namespace, which leaves no reason for the operator to be unable to access a member variable. Is this a problem with my prototype? Any help would be appreciated. Thanks.
The operator<< declaration and definition are actually not the same. In the friend declaration the second parameter is const contact &, and in the definition it's just contact&.
So the definition is actually unrelated to a friend declaration in the class, and defines another function which is not a friend of contact.

Declaring = and [] operators for a class on the header file, "must be a nonstatic member function" error

I've made a class Block and a struct coords and while implementing the operators i came up with the errors:
'coords operator[](const Block&, const size_t&)' must be a nonstatic member function
'bool operator=(Block&, const Block&)' must be a nonstatic member function
I've declared these 2 in the header file of the class Block as follows:
class Block
{
friend Block operator+(const Block&, const coords&);
friend Block operator+(const Block&, const Block&);
friend coords operator[](const Block&, const std::size_t&);
friend void operator+=(Block&, const coords&);
friend void operator+=(Block&, const Block&);
friend bool operator=(Block&, const Block&);
//...
};
Only the operators [] and = get this error, and I'm not sure why.
I've tried to change the return value and parameter types but it keeps getting the same problem.
Are these two operators special? Or is there an error on my declarations?
I've searched for ways to solve this problem, but couldn't find a suitable answer.
Thank you for the replies.
Not all operators can be overloaded using non-member functions. [] and = are two such operators. They can be overloaded only as member functions.
See http://en.cppreference.com/w/cpp/language/operators for more details.
Those operators cannot be declared as friends. Instead you should declare like this:
coords operator[](const std::size_t&);
bool operator=(const Block&);
Your operators are also not really following conventions. Operators += and = should be returning a Block& namely *this.
The reason is exactly what the error message says: those two have to be non-static member functions. Get rid of the friend from in front of them and remove the first argument.
Further, operator+= is usually implemented as a member function, too, although it doesn't have to be. But if it is, it gives you an easy way to implement operator+ without making it a friend.
#R Sahu's link was useful, showing that [] and = can no be declared as non-member, but it didn't really explain why.
#Baum mit aguen's link cleared some other questions too.
(Thanks for the information)
So, I adjusted my code to this new information as follows:
Block.h
class Block
{
public:
//...
coords* operator[](size_t);
Block operator=(Block);
//...
};
Block.cpp
//...
coords* Block::operator[](size_t index)
{
if(index >= 0 && index < block.size())
return &block.at(index);
coords *tmp = new coords(-1, -1);
return tmp;
}
Block Block::operator=(Block b2)
{
block.empty();
block.reserve(b2.block.size());
append(b2.block);
return *this;
}
//...
This way you can call *(*b1)[0] = c1; being Block* b1 and coords c1.
The friend modifier is useful for other types of implementations, although I only realized after that the implementation of inline had to be done in the header file, not on the cpp.
Block.h
class Block
{
public:
//...
friend std::ostream& operator<<(std::ostream&, const Block&);
friend std::ostream& operator<<(std::ostream&, Block&);
//...
};
inline std::ostream& operator<<(std::ostream& out, const Block& b)
{
// do something
return out;
};
inline std::ostream& operator<<(std::ostream& out, Block& b)
{
// do something
return out;
};
In this case, you need to pass the "this" parameter has to be passed to the function also as these are non-member functions and should be implemented outside the class, in the header file.
I hope this helps, good coding everyone.

Non-friend, non-member function accessing private data member

I am trying to use the istream function below to access the private data members numerator and denominator, however, I am getting errors about it being private. istream is a non-friend, non-member function (I cannot make it a friend). I understand that I cannot directly access the private members, but shouldn't my reference to MyFraction allow me to?
std::istream & operator>>(std::istream & sin, MyFraction & frac)
{
return sin >> frac.numerator >> frac.denominator;
}
I have getters (getNumerator() and getDenominator()), however, I cannot access the members that way either. I also get an error:
ambiguous overload for operator>>.
My getters do return by value:
inline int MyFraction::getNumerator() const
{
return numerator;
}
inline unsigned int MyFraction::getDenominator() const
{
return denominator;
}
What am I overlooking in this function?

Make a C++ overloaded operator a function pointer

Is there a way to overload an operator (specifically, operator >>) as a function pointer and then assign it a function at run-time? I want to be able to look at a file at run-time to ascertain the format of the file, then assign the correct function pointer to the operator to make it work as desired. I would assign the correct function in the constructor, before the operator would be called. I realize there are other (perhaps easier) ways to do the same thing, but I'm wondering if this is possible.
Here's what I tried:
bool Flag; // In global scope - set in main()
class MyClass
{
private:
int data;
friend istream & function1(istream & in, MyClass & c);
friend istream & function2(istream & in, MyClass & c);
public:
MyClass() :data(0) {operator>>=((Flag)?&function1:&function2);}
friend istream& (*operator>>)(istream & in, C & c);
};
// function1 and function2 definitions go here
int main (int argc, char **argv)
{
if (argc > 2)
Flag = ((atoi(argv[1]) > 1) ? 1 : 0);
MyClass mcInstance;
ifstream in(argv[2]);
in >> mcInstance;
return 0;
}
I get an error that looks like this:
error: declaration of ‘operator>>’ as non-function
You can't redefine the meaning of any actual function, including operators, at run-time directly: functions are immutable entities. What you can do, however, is to delegate within the function, including a user-defined operator, to a different function using a pointer to a function. For example:
std::istream&
std::operator>> (std::istream& in, MyClass& object) {
return Flag? function1(in, object): function2(in, object);
}
If you want to delegate through a function pointer, e.g., per object, you could set the function pointer up in your object and delegate through that:
class MyClass {
fried std::istream& operator>> (std::istream&, Myclass&);
std::istream& (*d_inputFunction)(std::istream&, MyClass&);
public:
MyClass(): d_inputFunction(Flag? &function1: &function2) {}
// ...
};
std::istream& operator>> (std::istream& in, MyClass& object) {
return (object.d_inputFunction)(in, object);
}