I have my parent class B and I overloaded the << operator. It seems my derived class D can use that operator, even tho I read everywhere that classes don't inherit friend functions from their parents. I used public inheritence by the way.
I am confused. Does this work because it is an overloaded operator, or any friend function is inherited by the child. Also if they are inherited, can I redefine them in any way?
If you have overloaded the friend operator<< for B, you may invoke that operator for D, even if it is not a freind of D:
class B {
public:
B(int i=0):v(i){}
private:
int v;
friend ostream& operator<< (ostream& os, const B& b);
};
class D:public B {
public:
D(string s=""s,int i=1) : B(i),v2(s){}
private:
string v2;
};
// access to the private members of B. B is accessed via a reference.
ostream& operator<< (ostream& os, const B& b){
return os<<b.v;
}
int main() {
B b;
D d;
cout << b <<endl; // calls operator<< for B
cout << d <<endl; // calls operator<< for the B sub-object of D
}
Online demo
For the D object, the B subject of D is used, since my code above passes argument by reference. If the overload would pass arguments by value instead of by reference, it would work as well, but the d object would be sliced into a B object.
In both case, the operator overload for the parent class is invoked.
You can overload the operator for the child class as well. But since friendship is not inherited, you'd need to define a new freindship if you need to access private members:
ostream& operator<< (ostream& os, const D& d){
//return os<<d.v<<d.v2; // not alloewed because D has no visibility on B's private members
return os << *static_cast<const B*>(&d) << d.v2;
}
Demo
The friendship for D is limited to D's private members and does not give access to B's private member. The usual way is to invoke the overload for B (here via a casting trick), and access the private member of D.
Of course, if operator<< only accesses public members we don't need any freindshop for the overload.
Related
When I have a small piece of code like this:
#include <iostream>
class A {
public:
friend inline std::ostream& operator<<(std::ostream& os, const A&);
};
inline std::ostream& operator<<(std::ostream& os, const A&) {
os << "Called\n";
return os;
}
class B {
public:
operator A() { return A(); }
};
int main()
{
A a;
std::cout << a;
B b;
std::cout << b;
}
the operator<< is called twice for both a and b, because b has an implicit user conversion operator for type A. But I was surprised when I modified the code to this:
#include <iostream>
class A {
public:
friend std::ostream& operator<<(std::ostream& os, const A&) {
os << "Called\n";
return os;
}
};
class B {
public:
operator A() { return A(); }
};
int main()
{
A a;
std::cout << a;
B b;
std::cout << b;
}
As you see, I have just transferred the definition inside the class rather than using a free function and marking it as a friend of the class. But this code gives an error which says no suitable function for operator<< is found for b.
Why does this problem happen?
It comes down to how C++ generates candidate functions when performing overload resolution. It's trying to find candidates for operator<<(std::cout, b). This means it performs unqualified name lookup which includes performing argument-dependent lookup (ADL). Let's take a look at how that works.
For the first code snippet, unqualified name lookup finds the declaration when it looks in the enclosing scope of the calling code, without needing to perform ADL. It sees inline std::ostream& operator<<(std::ostream& os, const A&) as a candidate, and then is able to apply the user-defined conversion to b to see that it's a valid function to use for overload resolution. All well and good.
For the second code snippet, though, we don't have a declaration of operator<< at file scope. The declaration and definition are entirely within the definition of the class A. That still might let us find it as a candidate function for std::cout << b, but it'll have to be through ADL. Let's check to see if it's actually visible through that:
Otherwise, for every argument in a function call expression its type
is examined to determine the associated set of namespaces and classes
that it will add to the lookup.
...
For arguments of class type (including union),
the set consists of
a) The class itself
b) All of its direct and indirect base classes
c) If the class is a member of another class, the class of which it is a member
d) The innermost enclosing namespaces of the classes added to the set
At any stage, would we look inside the definition of A when performing ADL with arguments std::cout and b? None of a), b), and c) apply to A because A isn't B, A isn't a base class of B, and A doesn't contain B as a member. Crucially, "any class to which the class is implicitly convertible" isn't used to generate candidates through ADL.
So ultimately in the second code snippet, the name lookup never sees the declaration of std::ostream& operator<<(std::ostream& os, const A&) and never realizes that it can apply a user-defined conversion to apply it with the appropriate arguments.
If we just make the function declaration (not definition) visible at file scope like so:
#include <iostream>
class A {
public:
friend std::ostream& operator<<(std::ostream& os, const A&) {
os << "Called\n";
return os;
}
};
std::ostream& operator<<(std::ostream& os, const A&);
class B {
public:
operator A() { return A(); }
};
int main()
{
A a;
std::cout << a;
B b;
std::cout << b;
}
This function declaration is once again found through ordinary unqualified name lookup, the user-defined conversion comes in during overload resolution, and the expected output of "Called" being printed twice is recovered.
because you use friend only if you want access to the members of the class but still they need to defined as a global function and then make them friend function of the class.
I have a base container class, which has a number of operators (=,+,-,+=,etc). It is expected that the logic of the operators will not need to be changed for the derived classes. Thus, ideally, I would like to use the base class operators for all of its derived classes without having to redefine them for each of the derived classes explicitly (with the exception of the assignment operator).
A solution that I came up with is demonstrated below based on a simple example. The solution seems to work, but I have doubts about the validity of the method for more complicated cases. Do you think it is valid to use this assignment "hack" in class B? What are the potential pitfalls of this method? Is there anything I missed? Are there easier ways of achieving the functionality that I need (i.e. using base class operators for derived classes)?
class A
{
protected:
int a;
public:
A(int ca)
{
a=ca;
}
A(const A& A1)
{
a=A1.a;
}
int geta() const
{
return a;
}
void seta(int ca)
{
a=ca;
}
const A& operator=(const A& A1)
{
a=A1.a;
return *this;
}
};
const A operator+(const A& A1, const A& A2)
{
A myA(A1.geta()+A2.geta());
return myA;
}
class B: public A
{
public:
B(int a): A(a) {}// ... using A::A;
const B& operator=(const B& B1)
{
a=B1.geta();
return *this;
}
const B& operator=(const A& B1)
{
a=B1.geta();
return *this;
}
};
int main()
{
B myB(4);
A myA(3);
//need this to work
myB=myB+myB;
cout << myB.geta();
myA=myA+myA;
cout << myA.geta();
int j;
cin >> j;
}
For the example given i don't see any problems that can happen. Of cause you can improve the code, first by returning non const reference in operator=, second i think by adding += op to your class, and using it's code inside global operator+ function.
But in general i think it should work fine. As for assignment operators - as soon as you have only POD types and no pointers, or references or handles you don't really need any.
It will become more complicated, however when pointers appear. You'll need to make sure you copy objects, pointed by them, or manage them some other way.
And you probably will not need to modify your operators as long as you don't add more members to derived classes, which also should take part in calculations.
In general you don't have to redefine functions in the base class for derived classes. With public inheritance your derived classes will have access to those functions and use their operation just fine. If you do want to re-define them (= operator for example), be sure you call the right one (virtual functions help in this case).
Consider classic virtual inheritance diamond hierarchy. I wonder to know what is the right implementation of copy and swap idiom in such hierarchy.
The example is a little artificial - and it is not very smart - as it would play good with default copy semantic for A,B,D classes. But just to illustrate the problem - please forget about the example weaknesses and provide the solution.
So I have class D derived from 2 base classes (B<1>,B<2>) - each of B classes inherits virtually from A class. Each class has non trivial copy semantics with using of copy and swap idiom. The most derived D class has problem with using this idiom. When it calls B<1> and B<2> swap methods - it swaps virtual base class members twice - so A subobject remains unchanged!!!
A:
class A {
public:
A(const char* s) : s(s) {}
A(const A& o) : s(o.s) {}
A& operator = (A o)
{
swap(o);
return *this;
}
virtual ~A() {}
void swap(A& o)
{
s.swap(o.s);
}
friend std::ostream& operator << (std::ostream& os, const A& a) { return os << a.s; }
private:
S s;
};
B
template <int N>
class B : public virtual A {
public:
B(const char* sA, const char* s) : A(sA), s(s) {}
B(const B& o) : A(o), s(o.s) {}
B& operator = (B o)
{
swap(o);
return *this;
}
virtual ~B() {}
void swap(B& o)
{
A::swap(o);
s.swap(o.s);
}
friend std::ostream& operator << (std::ostream& os, const B& b)
{ return os << (const A&)b << ',' << b.s; }
private:
S s;
};
D:
class D : public B<1>, public B<2> {
public:
D(const char* sA, const char* sB1, const char* sB2, const char* s)
: A(sA), B<1>(sA, sB1), B<2>(sA, sB2), s(s)
{}
D(const D& o) : A(o), B<1>(o), B<2>(o), s(o.s) {}
D& operator = (D o)
{
swap(o);
return *this;
}
virtual ~D() {}
void swap(D& o)
{
B<1>::swap(o); // calls A::swap(o); A::s changed to o.s
B<2>::swap(o); // calls A::swap(o); A::s returned to original value...
s.swap(o.s);
}
friend std::ostream& operator << (std::ostream& os, const D& d)
{
// prints A::s twice...
return os
<< (const B<1>&)d << ','
<< (const B<2>&)d << ','
<< d.s;
}
private:
S s;
};
S is just a class storing string.
When doing copy you will see A::s remains unchanged:
int main() {
D x("ax", "b1x", "b2x", "x");
D y("ay", "b1y", "b2y", "y");
std::cout << x << "\n" << y << "\n";
x = y;
std::cout << x << "\n" << y << "\n";
}
And the result is:
ax,b1x,ax,b2x,x
ay,b1y,ay,b2y,y
ax,b1y,ax,b2y,y
ay,b1y,ay,b2y,y
Probably adding B<N>::swapOnlyMewould resolve the problem:
void B<N>::swapOnlyMe(B<N>& b) { std::swap(s, b.s); }
void D::swap(D& d) { A::swap(d); B<1>::swapOnlyMe((B<1>&)d); B<2>::swapOnlyMe((B<2>&)d); ... }
But what when B inherits privately from A?
Here's a philosophical rant:
I don't think virtual inheritance can or should be private. The entire point of a virtual base is that the most derived class owns the virtual base, and not the intermediate classes. Thus no intermediate class should be permitted to "hog" the virtual base.
Let me repeat the point: The most derived class owns the virtual base. This is evident in constructor initializers:
D::D() : A(), B(), C() { }
// ^^^^
// D calls the virtual base constructor!
In the same sense, all other operations in D should be immediately responsible for A. Thus we are naturally led to writing the derived swap function like this:
void D::swap(D & rhs)
{
A::swap(rhs); // D calls this directly!
B::swap(rhs);
C::swap(rhs);
// swap members
}
Putting all this together, we're left with only one possible conclusion: You have to write the swap functions of the intermediate classes without swapping the base:
void B::swap(B & rhs)
{
// swap members only!
}
void C::swap(C & rhs)
{
// swap members only!
}
Now you ask, "what if someone else wants to derive from D? Now we see the reason for Scott Meyer's advice to always make non-leaf classes abstract: Following that advice, you only implement the final swap function which calls the virtual base swap in the concrete, leaf classes.
Update: Here's something only tangentially related: Virtual swapping. We continue to assume that all non-leaf classes are abstract. First off, we put the following "virtual swap function" into every base class (virtual or not):
struct A
{
virtual void vswap(A &) = 0;
// ...
};
Usage of this function is of course reserved only to identical types. This is safeguarded by an implicit exception:
struct D : /* inherit */
{
virtual void vswap(A & rhs) { swap(dynamic_cast<D &>(rhs)); }
// rest as before
};
The overall utility of this is limited, but it does allow us swap to objects polymorphically if we happen to know that they're the same:
std::unique_ptr<A> p1 = make_unique<D>(), p2 = make_unique<D>();
p1->vswap(*p2);
Virtual base generally means that most derived class of object is in control of it.
First solution: Reorganize your classes to be more fit for polymorphism. Make copy construction protected. Remove assignment and swap(). Add virtual clone(). Idea is that the classes should be treated as polymorphic. So they should be used with pointer or smart pointer. Swapped or assigned should be the pointer values, not the object values. In such context swap and assignment only confuse.
Second solution: Make B and C abstract and their pointers not to manage object lifetime. Destructors of B and C should be protected and non-virtual. B and C will not therefore be most derived classes of object. Make B::swap() and C::swap() protected and not swap the A subobject, may rename or add comment that it is business of inherited classes now. That removes lot of object slicing possibilities. Make D::swap() to swap A subobject. You get one swap of A.
Third solution: Make D::swap() to swap A subobject. That way the A subobject will be swapped 3 times and lands in correct place. Inefficient? The whole construct is probably bad idea anyway. I am for example not sure how well the virtual destructors and swaps cooperate here and lot of ways to slice objects are public here. It all seems similar to attempt of making virtual assignment operators that is bad idea in C++.
If something inherits from D on its order then it should make sure by swapping or not swapping A subobject that the count of swapping A is odd. It becomes to control so should take over and fix.
The private virtual idiom is one of ways to make a class final in C++. Nothing should be able to inherit from it. Interesting that you asked. If you ever use it, be sure to comment, it confuses most of the readers of code.
So I have a Base class:
class Base
{
public:
std::ostream& operator << (std::ostream & out, const Base & base);
}
And I have defined what the operator should do:
ostream& operator << (std::ostream & out, const Base & base)
{
return out << "output";
}
If I have a Derived class that extends Base and I want Derived to do the same thing as Base when its insertion operator is called, what is the best way to go about doing this? And by best I mean best way to not reuse code.
If you want to use a base-class method within a derived class, qualify the call:
void Derived::func()
{
//whatever else you want to do first
return Base::func();
}
Unless the method is private you have access to it, since Derived is a Base.
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