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

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.

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".)

Virtual inheritance / Polymorphism

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.

Why does clang create these implicit methods when a class contains a virtual method?

I'm working on a tool based on clang's AST, and I'm curious to know why clang works this way.
Here's my input. I have a very simple class that is defined like this:
class Foo {
int foo();
};
Then in my RecursiveASTVisitor, I have code that looks like this:
bool MyASTVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl *D) {
for (auto const & method : D->methods()) {
llvm::outs() << method->getQualifiedNameAsString() << "(";
for (auto const & param : method->params())
llvm::outs() << param->getType().getAsString() << ", ";
llvm::outs() << ")";
if (method->isImplicit())
llvm::outs() << " [implicit]";
llvm::outs() << "\n";
}
return true;
}
All this does is spit out the list of methods defined in all the classes that are visited. The output for this is as we'd expect:
Foo::foo()
Now, let's make a small change to our Foo class. Let's make the foo() method virtual:
class Foo {
virtual int foo();
};
Now my output changes:
Foo::foo()
Foo::operator=(const class Foo &, ) [implicit]
Foo::~Foo() [implicit]
My question is, why does adding a virtual method to a class cause clang to create an implicit assignment operator and destructor? If I add --std=c++11, it creates an implicit move-assignment operator as well. Is this an implementation detail of clang, or is it part of the C++ standard?
Turns out that I should just read the clang source code. SemaDeclCXX.cpp has a method called Sema::AddImplicitlyDeclaredMembersToClass. There's a comment about why it declares the implicit copy assignment:
if (!ClassDecl->hasUserDeclaredCopyAssignment()) {
++ASTContext::NumImplicitCopyAssignmentOperators;
// If we have a dynamic class, then the copy assignment operator may be
// virtual, so we have to declare it immediately. This ensures that, e.g.,
// it shows up in the right place in the vtable and that we diagnose
// problems with the implicit exception specification.
if (ClassDecl->isDynamicClass() ||
ClassDecl->needsOverloadResolutionForCopyAssignment())
DeclareImplicitCopyAssignment(ClassDecl);
}
So it does this in order to ensure that the implicitly defined methods, that may be virtual, end up in the right place in the vtable.

Object needs to let function access all its data

When using encapsulation and "tell, don't ask"-principle properly, there should be no reason for one to ask information from an object.
However, I've ran into a situation (let me know if this design itself is terrible) where I have an object with a member variable pointing to a function outside of the class.
At some point of my application, there's a need for my object to call the function and the function should then act based on my object's status.
Here's an example class:
typedef void(*fptr)(Foo*);
class Foo {
public:
Foo(string name, fptr function);
void activate()
{
m_function(this);
}
private:
string m_name;
fptr m_function;
};
That's the class, now the developer can use the class like so;
void print(Foo *sender)
{
cout << "Print works!" << endl;
}
int main(int argc, char **argv)
{
Foo foo("My foo", &print);
foo.activate();
// output: "Print works!"
}
This all works fine, but what if I want to print the name of the sender?
All the functions are defined outside of the class, by other developers, so there's no way to access private variables.
In C#, you can just use the partial keyword to add a method to an existing class.
This is not possible in C++ though.
I could just ignore encapsulation and create a setter and getter for name and all other properties that might be needed by the function in the future.
This is pretty terrible solution, I should basically create setter and getter for everything there is in my class, since the function can do anything to my object.
Besides what's the reason of encapsulation, if I'm just gonna ignore it when I want to?
An other solution would be a struct that holds the required properties inside it:
struct FooBar {
string name;
};
typedef void(*fptr)(FooBar);
void Foo::activate()
{
FooBar fb;
fb.name = m_name;
m_function(fb);
}
But this is not much different from not using encapsulation, and it doesn't seem like a too good solution either.
What would be the best approach for this problem?
I would make activate() an abstract method and all the class' properties protected.
Also, there's no need for the fptr:
class Foo {
public:
Foo(string name);
virtual void activate() = 0;
protected:
string m_name;
};
Now when someone wants to use your class, he just inherits his own from it:
class MyFoo : public Foo {
public:
MyFoo(string name);
virtual void activate()
{
cout << m_name << " says: Hello World!" << endl;
}
};
int main(int argc, char **argv)
{
MyFoo foo("My foo");
foo.activate();
// output: "My Foo says: Hello World!"
}
And if you need many different Foo's with different functionality, just inherit multiple classes instead of declaring multiple functions.
Edit: Instead of inheriting a new class for every different Foo instance, you could inherit one class for all of them with all the different methods.
Now all left for activate is to decide which method to call; use enum for this:
enum MyFooFunction {
printName,
printHello
};
class MyFoo : public Foo {
public:
MyFoo(string name, MyFooFunction function);
void printName() { cout << m_name << endl; }
void printHello() { cout << "Hello!" << endl; }
virtual void activate()
{
switch(m_function) {
case printName:
printName();
break;
case printHello:
printHello();
break;
}
}
protected:
MyFooFunction m_function;
};
Seen from the outside, private variables don't exist, so developers cannot possibly "want" to print them.
If they do want then either the class members (or better, queries in the class returning their contents) should be public, the function a member of the class, or in specific cases some friend mechanism may be used.
To summarize, don't set out to break encapsulation - instead, reconsider the abstraction behind your encapsulation and, if needed, create new queries for properties of your class which weren't foreseen as useful back when the class was designed - but now are.
You might want to change your function parameter type to const string & if the function should be able to see the string, but the rest of the outside world shall not see it. Also you might consider to use std::function<void(const string &)> instead of your function type. This has two fundamental advantages: You can pass closures (also called lambdas) to your constructor and you can read it more easily. The edited code would look like this:
class Foo {
public:
template <typename F>
Foo(string name, F && function)
: m_name (std::move(name))
, m_function(std::forward<F>(function))
{
}
void activate()
{
m_function(m_name);
}
private:
string m_name;
std::function<void(const string &)> m_function;
};
The client code would look like
int main(int argc, char **argv)
{
Foo foo("My foo", [](const string & s){ cout << s << endl; });
foo.activate();
// output: "My foo"
}
You see that the client does not need to define an extra function, but can simply do it 'inline'.
What you're asking is "How can I keep my members private, but still give callbacks some way of accessing them?"
When you look at it that way, your struct FooBar solution is actually pretty reasonable. The only problem is that it's a bit inefficient. You would be better off passing a const FooBar& instead of passing FooBar by value.
Your struct FooBar solution is even better than partial classes, because you can specify exactly which members the callback should have access to.
Edit: Reading your struct FooBar solution more closely, I see you're thinking of tediously copying the members individually before passing them to the callback. You can skip all that just by putting a FooBar object in your Foo class, like so:
struct FooBar {
string name;
};
typedef void(*fptr)(const FooBar&);
class Foo {
public:
Foo(string name, fptr function);
void activate()
{
m_function(data);
}
private:
FooBar data;
fptr m_function;
};
It's worth pointing out that, with this solution, the callbacks cannot access m_function, unless you decide to put it in FooBar. This is what I meant when I said that you can specify exactly which members the callback should have access to.
Let's face it, C++ access control was designed with some use cases in mind, and are generally usable, but never claimed to cover everything. If you can't solve the situation with just private and friend, and arbitrary functions must be allowed to access the internals, then best way is to make them public and move on.
Setters will not move you forward for sure, just add complexity for nothing. If data is effective public don't try to mask that fact pretending like it wasn't.
Look for the root cause -- why on earth outsides want your members and rearrange that.
I could just ignore encapsulation and create a setter and getter for name and all other properties that might be needed by the function in the future. This is pretty terrible solution, I should basically create setter and getter for everything there is in my class, since the function can do anything to my object.
True - this is basically making implementation details public (and in most cases, not something you should do).
An other solution would be a struct that holds the required properties inside it:
[...] But this is not much different from not using encapsulation, and it doesn't seem like a too good solution either. What would be the best approach for this problem?
Actually it is very different. Consider that you are actually calling an external function with normal parameters:
struct EventData { string name, yadayada; }
class Foo
{
public:
void activate()
{
m_function( EventData(m_name, yadayada) );
}
};
This is not accessing private data (Foo accesses it's own private data, m_function accesses it's own parameter values), but dependency injection.
There are no architecture compromises with this approach.

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.