Understanding pure-virtual functions - c++

The following code compiles fine:
struct A
{
const int a;
virtual void foo() = 0;
};
struct B : A{ };
void A::foo(){ std::cout << "foo" << std::endl; }
DEMO
The thing is the struct A is an abstract therefore we can't instanciate it. But we can subclass it and
struct A
{
const int a;
virtual void foo() = 0;
};
struct B : A{ };
void A::foo(){ std::cout << "foo" << std::endl; }
int main(int argc, char ** argv)
{
B b;
b.foo(); //error: implement pure-virtual
}
DEMO
still can't use the A's implementation of foo and I suspect it will never called. So, I have no idea about application of such definition... Yes, it's useful to provide a definition for a virtual destructors, but that's not the case.
Where the definition of pure-virtuals can be used?

You can call it explicitly.
struct A
{
const int a;
virtual void foo() = 0;
};
struct B : A
{
void foo();
};
void A::foo()
{
std::cout << "A::foo" << std::endl;
}
void B::foo()
{
A::foo(); // here
std::cout << "B::foo" << std::endl;
}
int main(int argc, char ** argv)
{
B b;
b.foo(); // prints A::foo followed by B::foo
}

But you can (and MUST) implement (if B is to be instantiable) an override for A's void foo(). And THAT implementation CAN (but definitely not required to) call the BASE implementation:
struct B : public A
{
virtual void foo() {A::foo();}
};
I HAVE implemented this scenario, where I had a very simple "base" implementation, but required all leafs to ACTIVELY decide to utilize this base (or not) by chaining back to this common implementation.

You can call it from within B. And since A::foo() is pure virtual, B needs to define foo:
struct A {
virtual void foo() = 0;
};
void A::foo(){ std::cout << "A::foo() ran" << std::endl; }
struct B : A {
void foo() {
A::foo(); // <--
std::cout << "B::foo() ran" << std::endl;
}
};
int main(int argc, char ** argv)
{
B b;
b.foo();
}

This is how you implement Interfaces in C++. You force subclasses to implement that method to be instantiated, and you operate polymorphically in your own code on that abstract base class, leaving the specific implementation to clients of your interface.
As far as the implementing in base class goes, I can only think of two reasons. One, to allow them to not have to special case destructors. And two, B can define its own implementation in terms of A::foo(), IE, a default implementation.

Related

Namehiding and overriding - Is there a way to make a function explicitly not overriding

I would like to hide a virtual method instead of override. I know for historic / compatibility reasons the override specifier is optional and overriding happens implicitly.
To stop overriding I usually adjusted the signature by adding a defaulted "Dummy" parameter. Is there a better way?
Assume this code:
#include <iostream>
class A{
public:
virtual void Foo()
{
std::cout << "A::Foo";
}
};
class B : public A
{
public:
void Foo() /*not override, just hide*/
{
std::cout << "B::Foo";
}
};
int main()
{
B b{};
A& a = b;
a.Foo(); //should print A::Foo - but prints B::Foo
}
What I did so far is this:
#include <iostream>
class A{
public:
virtual void Foo()
{
std::cout << "A::Foo";
}
};
template<typename T>
class reintroduce{};
class B : public A
{
public:
void Foo(reintroduce<B> = {}) /*not override, just hide*/
{
std::cout << "B::Foo";
}
};
int main()
{
B b{};
A& a = b;
a.Foo(); //should print A::Foo
}
The question is not too clear on the requirements of "hiding" but the following effectively "hides" the inherited method in the derived class, while not changing its visibility/accessibility in the base class.
#include <iostream>
class A {
public:
virtual void Foo()
{ std::cout << "A::Foo"; }
};
class B : public A
{
private:
using A::Foo;
};
int main()
{
B b;
b.Foo(); // error, cannot access private member
b.A::Foo(); // ok, calls A::Foo
A& a = b;
a.Foo(); // ok, calls A::Foo
}

How do I determine what a function will be called if it's virtual and when it is not?

Look at this excerpt of a program.
I see that cout << obj->foo(); call is not polymorphic. Actually, it is obvious, because it has no virtual specificator.
But I am confused with cout << ((B*)obj)->foo(); Why the program does not use the B's definition of virtual function and will call the third version of foo()?
#include <iostream>
using namespace std;
class A{
public:
int foo(){ return 1; }
};
class B: public A{
public:
virtual int foo(){ return 2; }
};
class C: public B{
public:
int foo(){ return 3; }
};
int main() {
A* obj = new C;
cout << obj->foo();
cout << ((B*)obj)->foo();
cout << ((C*)obj)->foo();
return 0;
}
A::foo() is not virtual. Calling foo() via an A* pointer (or A& reference) will call A::foo() directly without any polymorphic dispatch.
B::foo() is virtual. Calling foo() via a B* pointer (or B& reference) will dispatch the call to the most derived implementation of foo() that exists in the object that the B* (or B&) refers to.
C derives from B, and C::foo() overrides B::foo(), and obj points to a C object, which is why C::foo() gets called by polymorphic dispatch when foo() is called via a B* or C* pointer (or a B& or C& reference).
Because ((B*)obj)->foo(); behaves by design like B* b = (B*)obj; b->foo() and calls C::foo. You may call the base's method explicitly like ((B*)obj)->B::foo();.
#include <iostream>
using namespace std;
class A{
public:
int foo(){ return 1; }
};
class B: public A{
public:
virtual int foo(){ return 2; }
};
class C: public B{
public:
int foo() override { return 3; }
};
int main() {
A* obj = new C;
cout << obj->foo();
cout << ((B*)obj)->B::foo();
cout << ((C*)obj)->foo();
return 0;
}
Output: 123
Member function foo is virtual from class B downwards, i.e. also in C, even if it is not marked virtual or override there.
Thus, call ((B*)obj)->foo() is a virtual call, actually resulting in calling C::foo.

Method nonvisibility in base class despite definition in derived class; polymorphism and using `virtual` keyword

#include <iostream>
class A {
protected:
int foo;
};
class B : public A {
public:
B(int bar) { foo = bar; }
int method() { return foo; }
};
class C {
private:
A baz;
public:
C(A faz) { baz = faz; }
A get() { return baz; }
};
int main(void) {
C boo(B(1));
std::cout << boo.get().method() << std::endl;
return 0;
}
I have a base class A which B is a derived class of. Class C takes an A yet I have passed a derived class (B) in its place. No warnings or errors passing a B to C, but I'd like to have method visibility of method() in the above situation.
I'm not very familiar with virtual but I did try to add virtual int method() = 0; to A which lead to further errors.
Consider were I to add a second derived class:
class D : public A {
public:
D(int bar) { foo = bar; }
int method() { return foo+1; }
};
I'd like C to be able to take either B or D and my best assumption would be to take an A and let it handle it.
How do I use polymorphism correctly in this fashion?
Expected output with the below:
int main(void) {
C boo(B(1));
C boz(D(2));
std::cout << boo.get().method() << std::endl;
std::cout << boz.get().method() << std::endl;
return 0;
}
Would be:
1
3
First of all, in order to use A polymorphically, you need to add a virtual destructor, otherwise you will run into undefined behavior when trying to destroy the object. Then the method that you want to call through A must be virtual as well. If it shouldn't have an implementation in the base class itself, make it pure virtual:
class A {
protected:
int foo;
public:
virtual ~A() {}
virtual int method() = 0;
};
Then in C you need to use pointers or references to A, since polymorphism only works with those.
If you want C to own the A, as your code example to suggest, then you need to provide a destructor deleting the pointer and you need to disable copying of the class (or decide on some useful semantics for it):
class C {
private:
C(const C&); // Don't allow copying
C& operator=(const C&); // Don't allow copying
A* baz;
public:
C(A* faz) : baz(faz) { }
~C() { delete baz; }
A& get() { return *baz; }
};
int main(void) {
C boo(new B(1));
C boz(new D(2));
std::cout << boo.get().method() << std::endl;
std::cout << boz.get().method() << std::endl;
return 0;
}
Ideally you would upgrade to C++11 and use std::unique_ptr<A> instead of A* as member. But even if you can't do that, consider using boost::scoped_ptr<A>, which will manage the deletion for you (you don't need the destructor) and will make the class non-copyable by default. It also provides better exception-safety to encapsulate allocations in smart pointers like that.
If you need to call method() of type B using base class type A there has to be lookup during the runtime. The lookup is necessary to answer the question: Which method should be called? - the one that corresponds the type in a current line? Or other method in inheritance hierarchy?" If you expect method() from class B to be called when you have pointer or reference to A then you have to create a lookup table. This table is called vtable (from virtual functions table) and it's defined by adding virtual keyword to functions.
#include <iostream>
class A {
public:
virtual ~A(){}
virtual int method() = 0;
protected:
int foo;
};
class B : public A {
public:
B(int bar) { foo = bar; }
int method() {
std::cout << "Calling method() from B" << std::endl;
return foo; }
};
class C {
private:
A* baz;
public:
C(A* faz) { baz = faz; }
A* get() { return baz; }
};
int main(void) {
A* element = new B(1);
C boo(element);
boo.get()->method();
return 0;
}
It prints "Calling method() from B". Please keep in mind that the code is for presentation purposes and it's not good from best practices perspective.

Call base virtual method by pointer to function from derived class

I need to call the base method A::foo() from derived class by pointer.
#include <iostream>
struct A{
virtual void foo() { std::cout << "A::foo()" << std::endl; }
};
struct B:A{
virtual void foo() { std::cout << "B::foo()" << std::endl; }
void callBase(void (A::*f)()){
(this->*f)();
}
};
int main(){
B* p=new B();
p->callBase(&A::foo);
}
This code output "B::foo". Is it possible to call A::foo() by pointer to method?
Well, you can do something similar using some tricks with overwriting the value of this. You probably should never try to do that though, vtable pointers aren't meant to be modified by hand.
To do what you described, we need to have the pointer to A's vtable. Our object p has only pointer to B's vtable, so we need to store second pointer in a field within A's constructor.
Here is the code:
#include <iostream>
struct A{
virtual void foo() { std::cout << "A::foo()" << std::endl; }
int *a_vtable_ptr;
// First, save value of A's vtable pointer in a separate variable.
A() { a_vtable_ptr = *(int**)this; }
};
struct B:A{
virtual void foo() { std::cout << "B::foo()" << std::endl; }
void callBase(void (A::*f)()){
int *my_vtable_ptr = *(int**)this;
// Then modify vtable pointer of given object to one that corresponds to class A.
*(int**)this = a_vtable_ptr;
(this->*f)(); // Call the method as usual.
// Restore the original vtable pointer.
*(int**)this = my_vtable_ptr;
}
};
// Function main() is not modified.
int main(){
B* p=new B();
void (A::*f)() = &A::foo;
p->callBase(f);
}
Output:
A::foo()
Process finished with exit code 0
Virtual methods are designed to implement polymorphism and pointers to virtual methods supports their polymorphic behavior. But you given the possibility to call the base method by explicitly calling p->A::foo().
So if you want to call base method by pointer, you should make it non-virtual (as #PasserBy mentioned in comments).
Code example:
struct A {
virtual void foo() { std::cout << "A::foo()" << std::endl; }
void bar() { std::cout << "A::bar()" << std::endl; }
void callBase(void (A::*f)()) { (this->*f)(); }
};
struct B : A {
virtual void foo() { std::cout << "B::foo()" << std::endl; }
void bar() { std::cout << "B::bar()" << std::endl; }
};
int main()
{
A* p = new B();
p->foo();
p->bar();
p->callBase(&A::foo);
p->callBase(&A::bar);
p->A::foo();
p->A::bar();
}
Output:
B::foo()
A::bar()
B::foo()
A::bar()
A::foo()
A::bar()

Inheritance with CRTP

I have these 3 classes.
class A
{
public:
virtual void Func() = 0;
};
template<class T>
class B : public A
{
public:
void Func()
{
cout << "In B" << endl;
static_cast<T*>(this)->Func();
}
};
class C : public B<C>
{
public:
void Func()
{
cout << "In C" << endl;
}
};
And, I do this:
int main(int argc, char **argv)
{
A *a = new C;
a->Func();
return 0;
}
And it prints : "In C".
If I do this,
int main(int argc, char **argv)
{
B<C> *a = new C;
a->Func();
return 0;
}
It again prints "In C"
What is going on?
You're calling a virtual member function of a class C object who has overloaded this function. It calls the function in class C.
Furthermore, this is not CRTP as the templated class B does not inherit from the class template parameter.
Func is virtual, a is a pointer to an instance of C, so C's version of Func is called.
The code is not complete, add #include and "using namespace std;". More importantly, you get the desired behaviour by removing the virtual function declaration in A.
In general, the main reason to use CRTP is to let the template know the type it receives and avoid doing a virtual call (or better, avoid making the method virtual).
template <typename T>
class ClassUsingSomething {
public:
void method1() {
// I need to call method2, I do this by casting, so it doesn't need to be virtual.
static_cast<T *>(this)->method2();
}
};
class A: public ClassUsingSomething<A> {
public:
void method2() {
//do something
}
};