Achieve operator overloading without using member functions and friend functions - c++

Is it possible for a non-member and non-friend function to achieve this?
Presume that it is a binary operator, which means we need to pass two arguments from different objects. How can it access the private members?

This is an example:
class Foo{
private:
int m_i;
public:
Foo(int i): m_i{i} {}
int get() { return m_i; }
};
Foo operator+(Foo& foo1, Foo& foo2){
return {foo1.get() + foo2.get()}; // you can not access m_i directly as you do in member functions and friend functions
}
Generally speaking, you use normal functions for operator overloading operators that don't modify the state left operand and don't need access to private or protected members directly.

Related

Polymorphism with a friend function in C++

I would like to combine the concepts of polymorphism and friendship. I am making a pure virtual member function of a base class a friend of another class. I would then like to override this pure virtual member function in the classes derived from that base class, and access private member data of the class who has such function as friend. See the code snippet below. The compiler complains when I refer to my_int in the derived classes member function add(). I understand friendship is a 1-to-1 relationship, but I wonder if there is any way around it so as to implement polymorphism. Do I just have to make the member functions of the different derived classes friends of the foo() class?
class foo {
private:
int my_int{};
public:
friend virtual int base::add();
};
class base {
public:
virtual int add() = 0;
};
class derived_1 : public base {
public:
int add() {
return my_int + 1;
}
};
class derived_2 : public base {
public:
int add() {
return my_int + 2;
}
}
First, with what you've displayed it's not going to work because my_int is a member of foo but in the base class tree there is no 'foo' to get the member from.
The easy answer would be to make the function take an int argument and do away with the use of friend entirely.
struct derived2 : base
{
int add(int arg) { return arg + 2; }
};
The use of 'friend' should make you seriously question whether what you are doing is a good answer, sometimes the answer to that question is 'yes' but not often. And the more friends you need the less often the answer remains 'yes'.
Another way would be to add a function to base:
int get_arg(foo & f) { return f.my_int; }
and make that function the friend rather than add, get_arg() would be called from each derived's add() in order to get the value to work with but get_arg is not itself virtual.
You might want to look here:
https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Virtual_Friend_Function
Intent
Simulate a virtual friend function.
Solution and Sample Code
Virtual friend function idiom makes use of an extra indirection to
achieve the desired effect of dynamic binding for friend functions. In
this idiom, usually there is only one function that is a friend of the
base class of the hierarchy and the friend function simply delegates
the work to a helper member function that is virtual. The helper
function is overridden in every derived class, which does the real job
and the friend function just serves as a facade.
class Base {
public:
friend ostream& operator << (ostream& o, const Base& b);
// ...
protected:
virtual void print(ostream& o) const
{ ... }
};
/* make sure to put this function into the header file */
inline std::ostream& operator<< (std::ostream& o, const Base& b)
{
b.print(o); // delegate the work to a polymorphic member function.
return o;
}
class Derived : public Base {
protected:
virtual void print(ostream& o) const
{ ... }
};

Why won't this code, implementing PassKey pattern, compile?

Here is the code, c++11 :
#include<stdio.h>
#include<iostream>
template<typename T>
class Passkey
{
friend T;
Passkey() {}
Passkey(const Passkey&) {}
Passkey& operator=(const Passkey&) = delete;
};
class Access;
class MyClass
{
public:
MyClass() {}
private:
void func(Passkey<Access>) { std::cout<<"here" << std::endl;}
};
class Access
{
public:
void tryme(MyClass& c) { c.func(Passkey<Access>());}
};
int main ()
{
MyClass c;
Access a;
a.tryme(c);
return 0;
}
Compiler is giving the following errors:
prog.cpp: In member function 'void Access::tryme(MyClass&)':
prog.cpp:21:12: error: 'void MyClass::func(Passkey<Access>)' is private
void func(Passkey<Access>) { std::cout<<"here" << std::endl;}
^
prog.cpp:27:56: error: within this context
void tryme(MyClass& c) { c.func(Passkey<Access>());}
As pewt said, MyClass::func() must be public in order for Access::tryme() to be able to access it. In the example you linked in the comments, Citizen::getSocialSecurityNumber() is actually public. And that is fine, because the access is limited in a different way.
Your MyClass::func() takes a Passkey<Access> parameter – and no one is actually allowed to construct such an object apart from the Access class itself. All of Passkey's functions are private. By construction, Access is the only friend of Passkey<Access>, so only Access can construct the “key” required to call func(). So func() behaves as if it were private, without actually being private itself.
func() is a private method for MyClass. Access can't call func unless it is made a friend of MyClass.
Making PassKey a friend of Access does not (as far as I know...) allow use of MyClass's private methods.
Via https://en.wikipedia.org/wiki/C%2B%2B_classes#Member_functions
The private members are not accessible outside the class; they can be accessed only through methods of the class.
And When should you use 'friend' in C++?

Declare C++ primitive type member whose address cannot be known?

I'd like to declare a primitive type member in a class that forbids usage of operator&(). In other words: I don't want anyone to ever take the address of this member (and possibly pass it to other classes or functions, etc.)
Is this possible without using a wrapper type?
You can declare operator&() as private which prevent the address being taken with the & prefix, but std::addressof can always be used to circumvent that. Taking the address cannot be prevented, but it can be made for difficult as a deterrent.
Assume your class is A
Put this in your class declaration
A* operator&() = delete;
Declare your member as private, and your getter doesn't return reference/pointer.
it works also for non primitive-class (with the cost of the copy)
class A
{
public:
const A* operator & () const = delete; // pre-require of OP
A* operator&() = delete; // pre-require of OP.
int getMember() const { return member; }
void setMember(int value) { member = value;}
// Other stuff.
private:
int member;
};

Operator Functions as Member Functions and Nonmember Functions

I am very confuse in getting the idea of operator overloading as a member and non member function.
What do we actually mean, when we overload operator as a non-member function and similarly what do we mean when we overload operator as a member functions. Although I know that the non-member functions are the friend functions.
If you overload an operator as a non-member function, you need to specify an object which you want to operate on specifically in your argument list.
If you overload it as a member function, the "this" pointer will do part of the work for you.
Consider the following example:
class Test {
public:
friend Test operator+(const Test &lhs, const Test &rhs); // Non-member function
Test operator+(const Test &rhs); // Member function
};
The difference between the two is that the non-member function doesn't have the this pointer that compiler conveniently passes for you whenever you're talking about a specific instance of a class.
The member function one has the lhs inferred, therefore you need to provide only the rhs.
Please do note that the "friend" is not necessary but if you want to access Test's private members, you need it.
Compiler can disambiguate based on the parameter count. If you wanted to declare friend Test operator+(const Test &rhs), it would complain about insufficiency of arguments because + is a binary operator. The lhs of a member function operator+ is "this".
example
class Foo {
public:
Foo operator+(Foo) // member variant
// declared inside the function
}; // end of class
Foo operator+(Foo lhs, Foo rhs) // non-member variant
{ // declared outside the class
// could be just a call to the member variant
lhs.operator+(rhs);
// I usually do this when implementing std::stream operators,
// don't remember why just now.
}
the non-member does not need to be friended but may be if it need access to internal state.
the non-member has some advantages when it comes to templated code and namespaces on some compilers if I remember correctly, It can also be fine to friend in the non-member variant to document that there is a function outside the class that is somewhat specific to this class. It tells me that if I change that class I may have to look over the non-member operator to make sure that I have not broken anything.
A small example: (I haven't tried compiling this code but I hope it works)
class MyClass
{
public:
MyClass operator+(const MyClass& other) const; //member operator declaration
friend MyClass operator-(const MyClass& first, const MyClass& second); //non-member operator friend declaration
private:
int _a;
}
//member operator definition
MyClass MyClass::operator+(const MyClass& other) const
{
MyClass result;
result._a = _a + other._a;
return result;
}
//non-member operator definition
MyClass MyClass::operator-(const MyClass& first, const MyClass& second)
{
MyClass result;
result._a = first._a - second._a;
return result;
}
Mind the differences: in the member operator definition I don't specify anything before the first _a after "=" - this->_a is assumed.
The member operator functions can be used only if an instance of your class is the first argument of the operator. If, for example you wanted to do something like 2 + myClassObject, you would need to override the non-member operator MyClass MyClass::operator+(int first, const MyClass& second) (or with whatever return value you want this to have).
Note also that I needed the friendship declaration only for my non-member operator to have an access to the private _a field.
Most operators should be defined as members.
class MyClass
{
...
public:
const MyClass& operator+=(const MyClass&);
};
Bit this is identical in behavior to the following:
class MyClass {...};
const MyClass& operator+=(const MyClass&, const MyClass&);
The implied this in the first example is analagous to the first parameter to the second example. If the second example needs access to the internal state of MyClass, it needs to be friended.
class MyClass
{
friend const MyClass& operator+=(const MyClass&, const MyClass&);
};
const MyClass& operator+=(const MyClass&, const MyClass&);
The prototypical exception to this is operator<< on std::ostream.
std::ostream& operator<<(std::ostream&, const MyClass&);
This is logically a member of your MyClass, but because of the ordering of the parameters it would have to be a non-member of both classes or a member of std::ostream. Because you can't add members to std::ostream, this must be defined as a non-member.

Operator Overloading for Objects in Multiple Classes

So can you overload operators to handle objects in multiple classes (specifically private members.)
For example if I wanted == to check if a private member in Class A is equal to objects in a vector in Class B.
For example:
bool Book::operator==(const Book& check){
return(((ISBN1 == check.ISBN1) && (ISBN2 == check.ISBN2) && (ISBN3 == check.ISBN3)
&& (ISBN4 == check.ISBN4)) || (title_ == check.title_));}
Everything in that overload is part of the Book class, however what if I wanted to do something like this.
if(*this == bookcheckout[i])
with bookcheckout being part of a Library class. The == would fail in trying to compare title_ to a title_ stored in a vector of the Library class.
It's odd because I have the program doing the exact same thing in two different places, but in one place it's working and in the other it isn't.
Answered: had to have the function that the operator was in be a member function of the same class that the operator was a member function of
If you make operator friend or member of one class, it will be able to access its private members. To access privates of both, operator will have to be free standing friend of both.
That is a bit unwieldy, so consider making public interface for interesting things instead.
(suppressed all puns about accessing private parts of multiple entities)
Here is how you can make a very friendly operator, but again, this is not a good solution.
(didn't compile the code)
class B;
class A
{
friend bool operator==(const A&, const B&);
private:
int private_;
};
class B
{
friend bool operator==(const A&, const B&);
private:
int private_;
};
bool operator==(const A& a, const B& b)
{
return a.private_ == b.private_;
} class B;
This is a better way -- just make public getters and use them in operator.
class A
{
public:
int GetPrivate() const { return private_; }
private:
int private_;
};
class B
{
public:
int GetPrivate() const { return private_; }
private:
int private_;
};
bool operator==(const A& a, const B& b)
{
return a.GetPrivate() == b.GetPrivate();
}
You also can make operator to be part of one of the classes, if you need privates from it alone.
Read up on operator overloading syntax for more.
You don't specify the type of bookcheckout, so I can't be sure, but I think that your operator== will work without change.
For instance, if the code is:
class Library
{
public:
const Book & operator[] (int i);
};
Library bookcheckout;
Then your if statement will call the operator== you have without a problem.
Yes. If you need to access private members, consider providing an appropriate public interface for them OR go for friend class. It is usually better to avoid it though. To handle a specific type, implement operator== with an instance of that type.
You can, but you would need to make either 'bool operator==(A a, B a)' 'friend' of class A if you are using a free function or make class B 'friend' of class A if you implement the comparison operator as a class member function.
You can avoid the friendship requirement by providing a public accessor to the private member in class A