Virtual inheritance / Polymorphism - c++

So I'm looking at some weird cases of Polymorhpism and
ambiguity. And there's one case which I cannot understand. I don't understand why the last line of the code below act this way.
#include <stdio.h>
#include <iostream>
class Article
{
public :
virtual bool compare(Article *a) { std::cout << "ACA" << std::endl;}; // ACA
};
class Clothe : public Article
{
public :
bool compare (Clothe *c) { std::cout << "CCC" << std::endl;}; // CCC
bool compare (Article *a) { std::cout << "CCA" << std::endl;}; // CCA
};
int main()
{
Article *pta1 = new Article;
Article *pta2 = new Clothe;
Clothe *ptv1 = new Clothe;
pta1->compare(pta2); // print ACA
pta2->compare(pta1); // print CCA
pta2->compare(pta2); // print CCA because compiler needs to explore pta2 to determine which compare to use.
// pta2 is instanced as a Clothe, so one of Clothe's compare will be called.
// And judging by its declaration pta2 is an Article (even thought it's instanced as a Clothe),
// so it will Call Clothe::Compare(Article*). I'm OK with this
pta2->compare(ptv1); // print CCA ??? WHY , pta2 is explored, thus it's type is determined to be of type Clothe.
// And ptv1 is declared as a Clothe, so it should call Clothe::compare(Clothe* c)
// should print CCC, shouldn't it ?
}
I'm lost. I don't understand how g++ resolve the ambiguity that way.
Any help / explanation would be nice. Thanks for reading, and even more thanks to those who answer.
PS : I know compare should return bool, but it's not really important here.
EDIT : typo slided during my on-the-fly translation of variable names, names were originally in french sorry for that. It's fixed now

This line
pta2->compare(ptv1);
prints CCA because there is only a virtual function bool compare(Article *a) in the base class.
Your assumption about pta2 is wrong.
pta2 is explored, thus it's type is determined to be of type Clothe.
Which is not the case. The type of pta2 is Article * and nothing else. It only points to a Clothe object and it is therefore possible to call functions of Clothe through it, if (and only if) they are present and virtual and the base class and overrided (with the same Signature!) in the derived class.
Simply speaking:
The compiler can only "find" overloads in the derived class which are present and virtual in the base class if the call is performed via base class pointer.
What is happening here:
pta2 is a pointer to Article. Thus, when calling compare, the different possibilities of compare functions in Article are considered.
The only match is bool Article::compare (Article *a).
Now the compiler finds compare in Article to be virtual and uses some internal mechanism to make a virtual call through the 'vtable' of the object.
As Clothe overrides bool compare (Article *a), the overrided function is called.
The Base class knows nothing about bool compare (Clothe *c) since it does not know anything about Clothe and therefore the output is not CCV.

Related

Why does the member function name lookup stay in the parent class?

Motivation, if it helps: : I have struct member functions that are radial-basis-function kernels. They are called 1e06 x 15 x 1e05 times in a numerical simulation. Counting on devirtualization to inline virtual functions is not something I want to do for that many function calls. Also, the structs (RBF kernels) are already used as template parameters of a larger interpolation class.
Minimal working example
I have a function g() that is always the same, and I want to reuse it, so I pack it in the base class.
The function g() calls a function f() that is different in derived classes.
I don't want to use virtual functions to resolve the function names at runtime, because this incurs additional costs (I measured it in my code, it has an effect).
Here is the example:
#include <iostream>
struct A
{
double f() const { return 0; };
void g() const
{
std::cout << f() << std::endl;
}
};
struct B : private A
{
using A::g;
double f() const { return 1; };
};
struct C : private A
{
using A::g;
double f() const { return 2; };
};
int main()
{
B b;
C c;
b.g(); // Outputs 0 instead of 1
c.g(); // Outputs 0 instead of 2
}
I expected the name resolution mechanism to figure out I want to use "A::g()", but then to return to "B" or "C" to resolve the "f()" function. Something along the lines: "when I know a type at compile time, I will try to resolve all names in this type first, and do a name lookup from objects/parents something is missing, then go back to the type I was called from". However, it seems to figure out "A::g()" is used, then it sits in "A" and just picks "A::f()", even though the actual call to "g()" came from "B" and "C".
This can be solved using virtual functions, but I don't understand and would like to know the reasoning behind the name lookup sticking to the parent class when types are known at compile time.
How can I get this to work without virtual functions?
This is a standard task for the CRTP. The base class needs to know what the static type of the object is, and then it just casts itself to that.
template<typename Derived>
struct A
{
void g() const
{
cout << static_cast<Derived const*>(this)->f() << endl;
}
};
struct B : A<B>
{
using A::g;
double f() const { return 1; };
};
Also, responding to a comment you wrote, (which is maybe your real question?),
can you tell me what is the reasoning for the name lookup to stick to the base class, instead of returning to the derived class once it looked up g()?
Because classes are intended to be used for object-oriented programming, not for code reuse. The programmer of A needs to be able to understand what their code is doing, which means subclasses shouldn't be able to arbitrarily override functionality from the base class. That's what virtual is, really: A giving its subclasses permission to override that specific member. Anything that A hasn't opted-in to that for, they should be able to rely on.
Consider in your example: What if the author of B later added an integer member which happened to be called endl? Should that break A? Should B have to care about all the private member names of A? And if the author of A wants to add a member variable, should they be able to do so in a way that doesn't potentially break some subclass? (The answers are "no", "no", and "yes".)

Is there a possibility to print the name of the class an iterator points to?

Assume I have a program that works according to the following hierarchy:
And I have a linked list container of Human * which I am iterating over with std::list<Human *>::iterator human. The following iterator can point either Men, Women and Flying Men. Is there a possibility, maybe something like typeid(*human).name() that will return the name of the class that the pointed object belongs to? When I use typeid.name() I get class Human *.
Selecting an execution path in runtime based on type inspection is bad since it places knowledge where it shouldn't be and makes it harder to add new types since all checks have to be expanded with the new type id.
Instead, define an interface that allows all types that need it create their own versions. Here is a compilable example that you can copy and play around with. Notice that adding a new type that should be serialized doesn't change any code in existing classes and no new tests are needed. And, as a bonus, everything is type checked at compile time, making it impossible to add a call with an object of the wrong type.
#include <iostream>
#include <list>
#include <boost/foreach.hpp>
class Output {
public:
// Whatever operations needed
int Write(int value) {
std::cout << value << std::endl;
return 0;
}
};
class Human {
public:
virtual ~Human() {}
virtual int Serialize(Output& output) = 0;
};
class Men : public Human {
public:
int Serialize(Output& output) {
return output.Write(17);
}
};
class Women : public Human {
public:
int Serialize(Output& output) {
return output.Write(42);
}
};
int main(int argc, char* argv[]) {
Output output;
Men men1;
Men men2;
Women women1;
Women women2;
std::list<Human*> toSerialize;
toSerialize.push_back(&men1);
toSerialize.push_back(&women1);
toSerialize.push_back(&men2);
toSerialize.push_back(&women1);
BOOST_FOREACH(Human* human, toSerialize) {
human->Serialize(output);
}
return 0;
}
You can use typeid on the object **human itself, rather than the pointer, which always has type Human* whatever it points to. As long as Human is polymorphic (that is, it declares at least one virtual function), that will give you the type info for the dynamic type of the object.
Note that the name is not necessarily human-readable, or even unique; my compiler gives the mangled name 3Man if the pointer points to type Man, and other compilers may give other nastiness. If you want a nice human-readable name, you'll have to declare your own virtual member function to return one.
No. Typeinfo is the best reflection you're going to get. If you really need this, make a virtual member function that returns the proper names.
Yes, but your classes must have a virtual function. The best place would be to use a virtual destructor, since it is most likely needed sooner rather than later anyway.
Also note that typeid is not defined to give you a readable name. If it does with the compilers you currently target, great. If not, you may need to add a virtual function like const std::string &className() const to get what you want.

C++ Inheritance and virtual keyword on base_class with derived class

Sorry maybe I should rewrite my question in a better way.
I've a base class name ABC that have function name.
void saysez(ostream &os) const // this is NOT virtual!!
{ os << sez; }
and derived class name DEF that also have function name
void saysez(ostream &os) const { os << extra << " ";
scary::saysez(os);
So as we can see from the above code both having same signature.
In my understanding if there is no virtual keyword specified it should use the base class function but in my walkthrough practice the output it turned out that it is using the derived's function.
So I'm wondering why it is used the derived's function over base's function?
Below is the call from int main
w.saysez(cout); cout << '\n';
w is the object from derived class.
Below is the link to the snipped code with an output
http://codepad.org/Pz5jwMVP
I have a hard time understanding your question. The virtual keyword seems irrelevant to this problem. Your class witch has a member function void saysez(ostream&) and when you create an instance of this class and call w.saysez, the compiler matches the definition of saysez it found in your implementation of witch.
The virtual keyword really doesn't matter here. If don't want to see the 'Double Double' part, then cast w to a scary:
((scary*)&w)->saysez(cout)
and you won't see the 'Double Double' part printed out.
Please see this or just about any other site that discusses the virtual keyword for more information.
Firstly, please correct me if I don't understand your question correctly.
We use inheritance for many reasons and one of them is to code efficiently. For example, in your case,
you want to inherit the class scary which means you want to have the functionality of class scary in the derived classes. You can copy all of the member functions in the based class to have the same functionality as the based calls, but what if you decide to change something in one of the functions? you have to change all of them. so it is inefficient way of coding.
Now in you class, you asking why is object w in this line w.saysez(cout); cout << '\n'; because both class scary and class which have the same member function, the w should look in its class first for a match, if it doesn't find it, it will then look in the based class. Therefore, your object is calling the saysez member function in its class.
hope this will help.
Here's a smaller sample you could have posted that still demonstrates your issue:
#include <iostream>
using namespace std;
#include <cstring>
class scary {
char is[31];
char sez[31];
public:
scary() {
strcpy(is, "Creep");
strcpy(sez, "boooo");
}
scary(const char i[], const char s[])
{
strcpy(is, i); strcpy(sez, s);
}
virtual void sayis(ostream &os) const { os << is; }
void saysez(ostream &os) const // this is NOT virtual!!
{ os << sez; }
};
ostream &operator<<(ostream &os, const scary &x) {
x.saysez(os);
os << ", said the ";
x.sayis(os);
return os;
}
class ghost: public scary {
public:
ghost():scary("Ghost", "Boo!")
{
}
};
class witch: public scary {
char extra[31];
public:
witch(): scary("Witch", "Toil and Trouble") {
strcpy(extra, "Double, Double");
}
void saysez(ostream &os) const {
os << extra << " ";
scary::saysez(os);
}
};
int main() {
scary s;
ghost g;
witch w;
cout << s << '\n' << g << '\n' << w << '\n';
return 0;
}
Output:
boooo, said the Creep
Boo!, said the Ghost
Toil and Trouble, said the Witch
In witch's constructor, you set the sez array to "Toil and Trouble" and then in saysez declared in witch you print out extra and call scary's saysez function which prints out sez. This happens because it is possible (but not encouraged) to override non-virtual member functions.
I am guessing that w is declared as an element of type witch, so of course it is going to call witch::saysez(). If, though, you did:
scary* w2 = new witch();
w2->saysez(cout);
...then you should see the scary::saysez() behavior.
It looks like you have misunderstood how non-virtual functions work with inherited classes. Both virtual and non-virtual functions can be overridden. On an object of class Foo, if you call Foo::MyNonVirtualFn(), it will just execute the body of Foo::MyNonVirtualFn(). If Foo has a superclass that implements MyNonVirtualFn(), or if the object it's being called on is actually an instance of a subclass of Foo that overrides MyNonVirtualFn() -- none of that matters. If the function call is to Foo::MyNonVirtualFn(), then that is the version of the function that runs. (If you aren't explicit about what version of MyNonVirtualFn() you're calling it infers it from the type that you're calling it with -- for pointer or reference types this might not be exactly the same as the type of the object.)
Virtual functions are different in that if you call Foo::MyVirtualFn() on an object it will check to see if the object is an instance of a subclass of Foo that has overridden MyVirtualFn(). So, for instance:
Base* base = new Base();
Derived* derived = new Derived();
Base* derived_as_base = derived;
base->MyNonVirtualFn(); // Calls Base::MyNonVirtualFn().
derived->MyNonVirtualFn(); // Calls Derived::MyNonVirtualFn().
derived_as_base->MyNonVirtualFn(); // Calls Base::MyNonVirtualFn() because it's called on a Base*.
base->MyVirtualFn(); // Calls Base::MyNonVirtualFn().
derived->MyVirtualFn(); // Calls Derived::MyNonVirtualFn().
derived_as_base->MyVirtualFn(); // Calls Derived::MyNonVirtualFn() because it uses a lookup table.

Inheritance, pseudo polymorphism

Whilst digging through the STL sources (DinkumWare, SGI, STLport, etc..) and trying to make sense of their implementation choices (it's going well), I came across something I feel is a bit odd or rather ive never run into before.
Generally when one wishes to overload a member function in a derived class, you would prepend the base class member function signature with the virtual keyword, however at various points in the STL source this is not the case.
Here is a cut-down version of what I'm seeing in the STL implementations:
template <typename T> class A {
public:
void func( ) { std::cout << "inside A func( )" << std::endl; }
};
template <typename T> class B : public A<T> {
public:
void func( ) { std::cout << "inside B func( )" << std::endl; }
};
The compiler seems fine with this pseudo-polymorphism, where as I was expecting an error something along the lines of:
error C2535: 'void B<T>::func(void)': member function already defined or declared
Would someone be kind enough to explain what is going on here?
PS: This also seems to work without the classes being templates too.
'Regards
Without the virtual keyword - when redefining a function, you are hiding the super's function.
In your case, by redifining func(), you tell the compiler there is a new function for B, which is different from A's.
Though, because it is not declared virtual, you will see this affect only if you invoke func() from a variable of type B. A variable of type A which holds a B, will invoke A's func().
A *a = new B;
a->func()
will invoke the first [A's] method.
To invoke B's method, you need the type to be B:
B *b = new B;
b->func()
The B<T>::func member simply shadows A<T>::func. When you call p->func() where A<T> *p points to a B<T>, A<T>::func is called, so there's no polymorphism.
#include <iostream>
struct A
{
void func() { std::cout << "Hello!\n"; }
};
struct B : public A
{
void func() { std::cout << "Goodbye!\n"; }
};
int main()
{
B b;
A *p = &b;
p->func();
b.func();
}
(Demo)
In the C++ standard, there's at least one place where this shadowing/name hiding is exploited: std::ifstream::rdbuf hides its ancestor's method by that name and actually changes its return type.
There clearly is no error because these functions are just overloads: A::func() has a signature taking an A object (a reference or a pointer) as first argument while B::func() has a signature taking a B object as first argument. That is, this is just overloading of two functions with different argument but the function name.
This is done in a few places to produce a different return type from a function which is essentially trivially forwarding to another function (at least, these are the places I can think of). This is just to make life a bit easier for users although it is actually more confusing than anything else. The examples I can think of (e.g. the rdbuf() function in streams) should have created a different name instead.
This is acceptable code, B<T>::func is just hiding A<T>::func.
A<int> a;
B<int> b;
a.func(); // inside A
b.func(); // inside B
A<int> *const pA = new B<int>();
pA->func(); // inside A
When calling func through a polymorphic type, it will call the function on the type of the pointer.

boost::bind with protected members & context

In the below code, there are two "equivalent" calls to std::for_each using boost:bind expressions. The indicated line compiles, the indicated failing line fails. The best explanation I can find in the standard amounts to "because we said so". I'm looking for "why the standard indicates this behavior". My suppositions are below.
My question is simply: Why does the indicated line compile and the equivalent following line fail to compile (and I don't want because "the standard says so", I already know that - I will not accept any answers that give this as an explanation; I'd like an explanation as to why the standard says so).
Notes: Although I use boost, boost is irrelevant to this question, and the error in various formats has been reproduced using g++ 4.1.* and VC7.1.
#include <boost/bind.hpp>
#include <iostream>
#include <map>
#include <algorithm>
class Base
{
protected:
void foo(int i)
{ std::cout << "Base: " << i << std::endl; }
};
struct Derived : public Base
{
Derived()
{
data[0] = 5;
data[1] = 6;
data[2] = 7;
}
void test()
{
// Compiles
std::for_each(data.begin(), data.end(),
boost::bind(&Derived::foo, this,
boost::bind(&std::map<int, int>::value_type::second, _1)));
// Fails to compile - why?
std::for_each(data.begin(), data.end(),
boost::bind(&Base::foo, this,
boost::bind(&std::map<int, int>::value_type::second, _1)));
}
std::map<int, int> data;
};
int main(int, const char**)
{
Derived().test();
return 0;
}
The indicated line fails with this error:
main.C: In member function 'void Derived::test()':
main.C:9: error: 'void Base::foo(int)' is protected
main.C:31: error: within this context
As noted, the supposedly equivalent statement above compiles cleanly (and if the offending statement is commented out, runs with the expected result of printing “5”, “6”, “7” on separate lines).
While searching for an explanation, I came across 11.5.1 in the standard (specifically, I’m looking at the 2006-11-06 draft):
An additional access check beyond
those described earlier in clause 11
is applied when a non-static data
member or nonstatic member function is
a protected member of its naming class
(11.2)105) As described earlier,
access to a protected member is
granted because the reference occurs
in a friend or member of some class C.
If the access is to form a pointer to
member (5.3.1), the
nested-name-specifier shall name C or
a class derived from C. All other
accesses involve a (possibly implicit)
object expression (5.2.5). In this
case, the class of the object
expression shall be C or a class
derived from C.
After reading this, it became evidently why the second statement failed while the first succeeded, but then the question came up: What is the rationale for this?
My initial thought was that the compiler was expanding the boost::bind templates, discovering that Base::foo was protected and kicking it out because boost::bind<…> was not a friend. But, the more I thought about this explanation, the less it made sense, because if I recall correctly, as soon as you take the pointer to a member (assuming you initially are within access control of the member), all access control information is lost (i.e. I could define a function that returns an arbitrary pointer to a member that alternately returns a public, protected or private member depending on some input and the returner would be none the wiser).
More I thought about it, and the only plausible explanation I could come up with why it should make a difference was in the case of multiple inheritance. Specifically, that depending on the class layout, the member pointer when calculated from Base would be different than that calculated from Derived.
It's all about "context". In the first call the context of the call is Derived which has access to the protected members of Base and hence is allowed to take addresses of them. In the second the context is "outside of" Derived and hence outside of Base so the protected member access is not allowed.
Actually, this seems logical. Inheritance gives you access to Derived::foo and not to Base::foo. Let me illustrate with a code example:
struct Derived : public Base
{
void callPrivateMethod(Base &b)
{
// this should obviously fail
b.foo(5);
// pointer-to-member call should also fail
void (Base::*pBaseFoo) (int) = &Base::foo; // the same error as yours here
(b.*pBaseFoo)(5);
}
};
The reason for this restriction is enforcement of access control across different classes that share a common base.
This is reinforced by notes in Core Language Defects Report defect #385, the relevant part copied here for reference:
[...] the reason we have this rule is that C's use of inherited protected members might be different from their use in a sibling class, say D. Thus members and friends of C can only use B::p in a manner consistent with C's usage, i.e., in C or derived-from-C objects.
As an example of something this rule prevents:
class B {
protected:
void p() { };
};
class C : public B {
public:
typedef void (B::*fn_t)();
fn_t get_p() {
return &B::p; // compilation error here, B::p is protected
}
};
class D : public B { };
int main() {
C c;
C::fn_t pbp = c.get_p();
B * pb = new D();
(pb->*pbp)();
}
The protected status of D::p is something we want the compiler to enforce, but if the above compiled that would not be the case.