Similar, but not identical to, THIS QUESTION:
A
/ \
B C
\ /
D
What I want is:
struct A { virtual void func (void) = 0; };
struct B : virtual A { void func (void) {} };
struct C : virtual A { void func (void) {} };
struct D : B,C { void func (void) {} };
int main ()
{
A *p = new D();
((C*) p)->func(); // do C::func
((B*) p)->func(); // do B::func
}
According to THIS QUESTION this does not seem to be a problem so long the inheritance is just multiple inheritance and not a diamond. why does this not work with a diamond shape?
Apparently its ambiguous, but what I want to be able to do is cast the pointer and hence use a different parent implementation of the virtual function, i.e.:
((C*) p)->func(); //does C::func
If I run the code above I run into the error:
error: cannot convert from pointer to base class 'A' to pointer to derived class 'C' because the base is virtual
((C*)p)->func();
which I tried to google but cannot find anywhere
Since func is virtual throughout the hierarchy, any direct call to func through a pointer to any of the types involved will call D::func. To do the cast in the code in the question, use dynamic_cast<C*>(p). But that doesn't remove the virtual-ness of func, so that will end up calling D::func, just as p->func() does.
To get rid of the virtual-ness, you have to name the class as well as the function. In a simpler context:
D *d = new D;
d->C::func(); // calls C::func
When you have a pointer to the base type instead of a pointer to the derived type you have to convert the pointer to a type that has C::func. That conversion is done with dynamic_cast, like this:
A *p = new D;
dynamic_cast<C*>(p)->C::func();
Depending on your compiler, you might have to fiddle with your class definitions a bit to get rid of linker errors. Some compilers get confused with inheritance from classes with no non--inline functions.
Related
Why does this compile, if A has no virtual functions?
class A {
int a = 42;
};
class B {
void* f() {
return dynamic_cast<A*>(this);
}
virtual void my_virtual() {};
};
Note: Though it makes no sense to write something like this, this was the result of a refactor, after the base class was removed. I feel like there should have been a compiler error.
Because it's not a requirement, and it shouldn't be an error.
Consider the following addition to your classes (after making B::f() public):
class C: public A, public B
{
};
int main()
{
C c;
void* p = c.f();
}
which should, and does, return to p a pointer to the A subobject of c.
Only the conversion source is required to be of polymorphic type, and that is only if it is not known at compile time that the target is a base class of the source.
In the latter case, a decent compiler will not do any conversion at runtime.
#include <iostream>
struct A {
virtual void a() {
puts("A");
}
};
struct B {
virtual void b() {
puts("B");
}
};
struct C {
virtual void c() {
puts("C");
}
};
struct D : public A, public B, public C {
virtual void c() {
C::c();
puts("cd");
}
};
int main() {
A* obj = new D;
obj->a();
B* b = (B*)obj;
b->b();
C* c = (C*)obj;
c->c();
return 0;
}
I have this code where I have non virtual multiple inheritance. However, it seems to call the wrong virtual function when I call the functions in the main function.
Instead of outputting:
A
B
C
cd
It outputs:
A
A
A
What puzzles me is that when I change the code to doing this:
B* b = (B*)(D*)obj;
b->b();
C* c = (C*)(D*)obj;
c->c();
It outputs what I would expect (see above). Afaik doing a double pointer cast like this wouldn't effect anything and would be optimized out by the compiler. But it seems to be changing what virtual function is being called.
Can someone explain why this would change what virtual function is being called?
Notes:
I printed the pointers at each step, they are the same.
I want to avoid using dynamic_cast (although it does work) as it's too slow for what I need it to do.
Can someone explain why this would change what virtual function is being called?
Generally, a C-style cast between pointer types won't change the value of the pointer and so will have no effect. There is, however, one exception.
A cast between a class and a parent or child class can change the value of the pointer. For example:
class A
{ int a; };
class B
{ int b; };
class C : public A, public B
...
Now, a pointer to an instance of class A will probably have the same value as a pointer to its a member and a pointer to an instance of class B will probably have the same value as a pointer to its b member. A pointer to an instance of class C can't have the same value as a pointer to both its A::a and its B::b members since they're distinct objects.
A function expecting a B* can be passed a C* since a C is a B. Similarly, a function expecting an A* can be passed a C* for the same reason. But at least one of these will require a value change to the pointer.
So casts between these types will change the values, the others are all no-ops.
Of course, all of this is UB. You are casting between unrelated types and then dereferencing them.
I want to avoid using dynamic_cast (although it does work) as it's too slow for what I need it to do.
That seems very hard to believe.
If we create an object pointer to base class class which points to its child class object then we use virtual key word for late binding
So.,in case of late binding,, our code goes like this :-
#include<iostream>
using namespace std;
struct A{
virtual void print() {
cout<<"function1";
}
};
struct B : public A{
void print(){
cout<<"function2";
}
};
struct C : public B{
void print(){
cout<<"function3";
}
};
int main(){
A* a = new C();
A* p = new B();
a->print();
p->print();
}
Now my question is : when we use virtual keyword in base class, all the functions of derived classes created in base class will become virtual.
In multilevel inheritance, is there any way so that we can stop the function of class c from being virtual??
Any way to break this chain of virtual functions ?
Sorry for any mistakes in question but i tried my best.. ☺️☺️
It is not possible to make a function that is already virtual be not virtual in a child class.
Virtuality is a property of the top-level base class, not the child classes. Once a method has been marked as virtual, and pointer to that class must use dynamic dispatch for that function when calling because the pointer could be pointing to a child class that has overridden the behaviour.
Consider this code:
A a;
B b;
C c;
A * ap = &a;
A * bp = &b;
A * cp = &c;
ap->print(); // 'function1'
bp->print(); // 'function2'
cp->print(); // 'function3'
Here, the calls to print cannot tell which function to call at compile time, they absolutely must use dynamic dispatch.
However, you can make C::print behave like A::print
struct C : public B {
void print() {
A::print();
}
};
Which results in:
ap->print(); // 'function1'
bp->print(); // 'function2'
cp->print(); // 'function1'
And if the behaviour of A::print() changes, C::print() mirrors those changes.
This will still be overridable though, unless you use the final keyword as outlined below.
Original answer:
I believe you are looking for the final specifier.
It's only available as of C++11 though.
To quote en.cppreference's page about the final specifier:
When used in a virtual function declaration or definition, final
ensures that the function is virtual and specifies that it may not be
overridden by derived classes. The program is ill-formed (a
compile-time error is generated) otherwise.
And a variation of the example they give, demonstrating the solution to your problem:
struct A
{
virtual void foo();
};
struct B : A
{
void foo() final; // B::foo is overridden and it is the final override
};
struct C : B
{
void foo() override; // Error: foo cannot be overridden as it's final in B
};
I understand why you cannot simply cast a derived class member function pointer to base class member function pointer as explained here.
But, given this snippet:
struct base
{
virtual void foo() = 0;
};
struct derived : base
{
void foo() override {};
};
struct invoker
{
typedef void(base::*target)();
invoker(base* b, target t)
{
(b->*t)();
}
};
template<typename B, typename D>
void (B::*cast(void (D::*method)()))()
{
return static_cast<void(B::*)()>(method);
}
derived d;
invoker bad(&d, &derived::foo); //C2664
invoker good(&d, cast<base>(&derived::foo));
I wanted to ask is it possible to decorate the base function signature so that compiler understands it is a pure virtual method and and it will be implemented somewhere across the hierarchy (otherwise I could not construct an object of type B)? I understand why I can't do this with normal functions, but IMHO in case of a pure virtual function the compiler has a guarantee it will be implemented (in case it was not done I would get an error about the class B not about the cast).
There's no need to manipulate the type of &derived::foo. One can just use &base::foo instead.
Pointers to member functions respect virtuality. This call
base* pBase = new derived;
auto pFoo = &base::foo;
(pBase->*pFoo)();
will actually call derived::foo, exactly like a simple call pBase->foo() would.
Even if there's a guarantee that it's implemented, it might use additional data members declared only in derived. A possible solution is to use function pointers and pass this as the first parameter (this also shows you why you cannot do it via virtual).
Consider the following diamond hierarchy:
struct base {
virtual void foo() = 0;
};
struct D1 : public virtual base {
virtual void foo() override;
};
struct D2 : public virtual base {
virtual void foo() override;
};
struct Derived : public virtual D1, D2 {
virtual void foo() final;
};
Now consider a scenario where a upcast is allowed from Derived::* to base::* . Which function should be invoked? The compiler loses information about which of D1::foo, D2::foo or Derived::foo you wish to call since that information has been cast away. To avoid this sort of ambiguity such an upcast is disallowed.
I have a class that contains some functions (none are virtual) and 2 more classes publicly inherit that class. In both the sub classes I override the same function of the base class.
After creating objects of all three classes in main (located at the same file), I call the original function with the baseclass object and the overridden functions with the derivedclass objects.
I was expecting all 3 function calls to run the original function from the base class (since I didn't use 'virtual' anywhere in the code), but I actually get each version of that function working according to the class in which it was defined (3 different versions).
I have the classes Base & Derived as follows:
struct Base
{
void foo();
};
struct Derived : Base
{
void foo();
};
in main:
int main()
{
Derived d;
d.foo();
}
I thought d.foo() should run Base::foo() if not using 'virtual'.
This is not "overriding"... and it doesn't need to be.
struct Base
{
void foo();
};
struct Derived : Base
{
void foo();
};
int main()
{
Derived d;
d.foo();
}
If I understand you correctly, then you were expecting this to execute Base::foo(), because the functions are not virtual and therefore one does not override the other.
But, here, you do not need virtual dispatch: the rules of inheritance simply state that you'll get the right function for the type of the object you run it on.
When you need virtual dispatch/overriding is a slightly different case: it's when you use indirection:
int main()
{
Base* ptr = new Derived();
ptr->foo();
delete ptr;
}
In the above snippet, the result will be that Base::foo() is called, because the expression ptr->foo() doesn't know that *ptr is really a Derived. All it knows is that ptr is a Base*.
This is where adding virtual (and, in doing so, making the one function override the other) makes magic happen.
You cannot override something that isn't virtual. Non-virtual member functions are dispatched statically based on the type of the instance object.
You could cheat by "overriding" a function by making it an inline function calling something indirectly. Something like (in C++03)
class Foo;
typedef int foo_sig_t (Foo&, std::string&);
class Foo {
foo_sig_t *funptr;
public:
int do_fun(std::string&s) { return funptr(*this,s); }
Foo (foo_sig_t* fun): funptr(fun) {};
~Foo () { funptr= NULL; };
// etc
};
class Bar : public Foo {
static int barfun(Bar&, std::string& s) {
std::cout << s << std::endl;
return (int) s.size();
};
public:
Bar () : Foo(reinterpret_cast<foo_sig_t*>)(&barfun)) {};
// etc...
};
and later:
Bar b;
int x=b.do_fun("hello");
Officially this is not overloading a virtual function, but it looks very close to one. However, in my above Foo example each Foo instance has its own funptr, which is not necessarily shared by a class. But all Bar instances share the same funptr pointing to the same barfun.
BTW, using C++11 lambda anonymous functions (internally implemented as closures), that would be simpler and shorter.
Of course, virtual functions are in generally in fact implemented by a similar mechanism: objects (with some virtual stuff) implicitly start with a hidden field (perhaps "named" _vptr) giving the vtable (or virtual method table).