I know this question must have been covered endless of times, but I've searched the previous questions, and nothing seems to pop.
It's about inheritance and virtual functions i C++. I have a problem with calling virtual functions in subclasses from the superclass.
Let me give an example. Start of with three classes, which inherit from each other.
class A {
void foo() { bar() }
virtual void bar() { }
};
class B : public A {
virtual void bar() { }
};
class C : public B {
virtual void bar() { // do something }
};
Now I wanna have a variable declared as B* but instantiated as C*.
B* myObject = new C();
myObject->foo();
When I do this, and call foo() on myObject, then A::foo() is calling bar(). But only B::bar() is called, not C::Bar() - which in reality myObject is, even though it's declared as B, which again affects that "// do nothing" doesn't get executed.
How do I tell A::foo(), that it needs to look at lowest implementation?
Makes sense?
// Trenskow
EDIT:
C::Foo is not the problem. Foo is being called in class A, as it's the only place it's implemented. The problem arises, when A:Foo calls Bar(). Then B:Bar is called and not C::Bar.
Maybe the problem is, that in my implementation, I only get a void* pointer to the object in A.
Like this:
void A:Foo(void *a) {
A* tmpA = static_cast<A*> (a);
tmpA->bar();
}
Now the compiler thinks, that tmpA is an A. But somehow it manages to figure that it's a B*, and calls B::Bar, when in fact tmpA is a C* and it should be calling C::Bar.
The following prints "A::foo C::bar" as expected. Are you getting something different? B::bar is never called because C is the actual runtime type of the object. In C::bar, you could call B::bar explicitly by adding B::bar(); to its body.
#include <iostream>
using namespace std;
class A {
public:
void foo() { cout << "A::foo "; bar(); }
virtual void bar() { }
};
class B : public A {
public:
virtual void bar() { cout << "B::bar" << endl; }
};
class C : public B {
public:
virtual void bar() { cout << "C::bar" << endl; }
};
int main()
{
B* c = new C();
c->foo();
return 0;
}
void A:Foo(void *a) {
A* tmpA = static_cast<A*> (a);
tmpA->bar();
}
This is undefined behaviour. You cannot cast a B* to a void*, then cast that void* back to an A*. If you want it to work properly, you have to ditch the void*. Alternatively, you could try dynamic_cast.
Assuming you mistyped your last block of code and the names match:
B* variable = new C();
variable->foo();
Then the C::Foo method is being called or you are using a terribly bad compiler.
(This also assumes that you don't actually have a compiler error in C::Foo, and that the comment is actually something like std::cout << "Hi mom!" << std::endl;)
Don't you mean:
B* myObject = new C();
myObject->foo(); // not variable->foo()
class A
{
public:
void foo() { bar(); }
virtual void bar() { std::cout << "A"; };
};
class B : public A
{
public:
virtual void bar() { std::cout << "B";};
};
class C : public B
{
public:
virtual void bar() { std::cout << "C"; }
};
This prints 'C' as expected.
I don't follow. You're saying
But only B::bar() is called, not
C::Bar()
No. You invoked the constructor of class C, which means that the vtable makes bar() point to C::bar(), so calling foo() in this case would go straight to C::bar().
If you want to force A::foo() to explicitly only call A's implementation, you can do that by just writing
void foo() { A::bar(); }
What exactly are you trying to do?
what compiler are you using? Visual Studio (IIRC) usually has the runtime type information turned off by default so maybe its just something simple as that?
Related
I have the following code:
struct A
{
virtual void foo() {std::cout << "A\n";}
};
struct B : public A
{
virtual void foo() {std::cout << "B\n";}
};
void bar(A * a)
{
a->foo();
}
Without changing this code, is it possible to cast bp pointer to B, so calling bar would print "A"?
int main()
{
B * bp = new B();
bar(/* do somethig*/ bp);
return 0;
}
Tried every cast I remebered:
int main()
{
B * bp = new B();
bar((A*)bp);
bar(static_cast<A*>(bp));
bar(reinterpret_cast<A*>(bp));
bar(dynamic_cast<A*>(bp));
return 0;
}
You could make a shim wrapper around B, and have the shim's virtual function dispatched to BWrap::foo() call directly to A::foo();.
There's not really any point in the example to carrying along the B& member variable reference, but for more interesting examples there may be a use case.
struct BWrap : public A
{
B& b;
BWrap(B& bb) : b{bb} {}
virtual void foo() { b.A::foo(); }
};
int main()
{
B* bp = new B();
BWrap bw{*bp};
bar(&bw);
}
If you insist on the A object being a base class subobject of a B object and on not modifying the first code snippet at all, then the only solution is to add an even more derived class that can override the virtual call as explained in the answer by #Eljay (which I completely forgot to think about when first writing this answer).
Other options are to create a complete A object, not a B object, or to modify bar to do a call without virtual dispatch by using a qualified name:
a->A::foo();
All of the casts you are showing have the same effect as the implicit conversion, except for reinterpret_cast which will cause undefined behavior when used this way.
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.
class A {
public:
A() { foo(); }
~A() { foo(); }
void foo() { cout << 3; }
void bar() { foo(); }
};
class B : public A {
void foo() { cout << 2; }
};
int main() {
B b;
b.bar();
return 0 ;
}
I compiled and ran it . The result is 333
... but I thought: when I call b.bar() . It would be directly to bar() and then call foo() function which is in class B because foo() in class A is overridden in class B . The result I thought is 323 . But I was wrong. Have I missed something ? Please help me to explain how it atually works #
THe problem is that you have a non virtual foo() so that A::bar() will call the only foo() it knows, being A::foo(), even if it's B that invokes it.
Try:
class A {
public:
A() { foo(); }
virtual ~A() { foo(); } // <<---------- recommendation
virtual void foo() { cout << 3; } // <<<--------- solves it
void bar() { foo(); }
};
class B : public A {
void foo() override { cout << 2; } // <<---------- recommendation
};
Additional infos:
Making foo() virtual in the base class allows each class to override this function, and be sure that the foo() that is invoked is will be the foo() corresponding to the object's real class.
It's a good practice then to use the keyword override in the derived classes: it's not mandatory, but in case you make a typo in the functions signature, you'll immediately notice with a compile-time error message.
Another good practice is to make your base class destructor virtual if you have at least one virtual function in the class.
A final remark: in B, foo()'s private. This is legal, but it's weird because the inheritance says that B is a kind of A, but you can't use B objects exactly as an A object.
Member A::foo is non-virtual and will therefore be statically bound wherever used. So when compiling A::bar, the call to foo() will be (statically) bound to the implementation A::foo(). This statical binding in A::foo will not be changed by the fact that you create an instance of derived class B later on.
If you call b.foo() in you main, however, B::foo will be bound.
In order to have B::foo to be called through A::bar, you'll have to declare A::foo as `virtual:
class A {
public:
A() { foo(); }
virtual ~A() { foo(); }
virtual void foo() { cout << 3; }
void bar() { foo(); }
};
Note that you'd also declare the destructor as virtual; non-virtual destructors do very rarely make sense.
You must include virtual in order to override the functionality stored in A.
Add to A
virtual void foo() { cout << 3; }
and to B
void foo() override { cout << 2; }
Should do the trick. Virtual functions are member functions whose behavior can be overridden in derived classes. As opposed to non-virtual functions, the overridden behavior is preserved even if there is no compile-time information about the actual type of the class. If a derived class is handled using pointer or reference to the base class, a call to an overridden virtual function would invoke the behavior defined in the derived class.
I have these two classes:
class A {
public:
A() { m_ptr = NULL; }
void (*m_ptr)();
void a() { if (m_ptr) m_ptr(); }
};
class B : public A {
public:
B() { m_ptr = b; }
void b() {
std::cout << "B::b() is called" << std::endl;
}
};
And I want to use them like this:
B b;
b.a();
and get the following to be called B::b().
Of course this is not being compiled as B::b is not of type void(*)().
How can I make it work?
UPDATE. To whom who asks "why?" and "what for?".
The class A is a very basic class which has many successors in production code. The class B is 6-th successor and I want to extend A (the most convinient place) to call there one more method (from B) which can be present and may be not in another successors af A and B.
A virtual method with empty body can be employed for that but it is ugly and I want to avoid it. Abstract method even more so (because of existing derived successors code).
I don't want to use external function of type void (*)() to not loose access to internal data of all hierarchy.
You can't make it work as your classes are defined now.
Calling a non-static member function of another class requires an instance of that class. You either need to store a reference to the object that owns the member function when storing the function pointer, or pass a reference to the object when you make the call to A::a.
You also need to declare m_ptr with the type void (B::*)(), which is pointer to member of B that is a function taking no parameters and returning void.
Look at this example:
class A {
public:
A() { m_ptr = nullptr; }
void a(B& b) { if (m_ptr) (b.*m_ptr)(); } // Now takes reference to B object.
void (B::*m_ptr)(); // Pointer to member function of B.
};
class B : public A {
public:
B() { m_ptr = &B::b; } // Adress of qualified function.
void b() {
std::cout << "B::b() is called" << std::endl;
}
};
Now we can call B::b like this:
B b;
b.a(b); // Pass reference to b when calling.
Your use of inheritence in this way is confusing as it implies that the real problem you are trying to solve is to invoka a member of a derived class through the base class. This is usually accomplished using a simple virtual function like this:
class A {
public:
virtual ~A() {}
void a() const { b(); } // Call b.
private:
virtual void b() const {}
};
class B : public A {
public:
virtual void b() const override { // C++11 override specifier (optional).
std::cout << "B::b() is called" << std::endl;
}
};
And used like this:
B b;
b.a(); // B::b is called.
Well, probably not the purpose of this exercise, but you can simply declare static void b() if you want to make it work.
Another option is to declare friend void b(), but then the "B::b() is called" printout would be stating a wrong fact.
I would suggest using CRTP since you want to avoid virtual mechanism. Note, however, your code might require some design changes to accommodate this pattern. But it does provide type safety and has no run-time overhead. Hope it helps.
Code on ideone.com:
#include <iostream>
#include <type_traits>
namespace so {
class B;
template<typename T>
class A {
public:
template<typename U = T, typename = typename std::enable_if<std::is_same<U, B>::value>::type>
void foo_A() {
std::cout << "foo_A : ";
static_cast<U *>(this)->foo_B();
}
};
class B: public A<B> {
public:
void foo_B() {
std::cout << "foo_B" << std::endl;
}
};
class C: public A<C> {
public:
void foo_C() {
std::cout << "foo_C" << std::endl;
}
};
} // namespace so
int main() {
so::B b_;
so::C c_;
b_.foo_A();
b_.foo_B();
//c_.foo_A(); Compile error: A<C>::foo_A() does not exist!
c_.foo_C();
return (0);
}
Program output:
foo_A : foo_B
foo_B
foo_C
take this simple code:
class A{
public:
virtual void foo() = 0;
void x(){ foo(); }
};
class B: public A{ foo(){ ... } };
main(){
B b;
b.x();
}
What I want is to build an abstract class that will have a function that will call a function expecting it to be implemented in the derived class
The question is that I can't seem to make that work, the compiler says it can't compile because it can't find the reference(or something like that) to the foo() to be executed in x() of the base class. Can this work? Can anyone give me an example of this?
EDIT: It seems that it just doesn't work when the "foo();" is inside the destructor of class A(the base one)...
It just got me confused. =[
EDIT2: how interesting this got. I just created a callfoo(){ foo(); } and now it compiles ok, but if I try to call the pure abstract function directly from within the destructor of Base class A, it gives me errors... weird. Anyone has any idea of this? O_o
any help on this please?
Thanks,
Jonathan
Update
It worked outside the destructor. Now I just got confused.
Try putting the "foo()" inside the destructor of the A(base) class, at least for me is not compiling...
any help plz?
There is nothing preventing you from doing that:
struct A {
virtual ~A() {}
virtual void f() = 0;
virtual void g() { f(); }
};
struct B : A {
void f() { std::cout << "B::f()" << std::endl; }
};
// ...
A* a = new B;
a->g(); // prints "B::f()"
As for calling a pure virtual function from the destructor (or constructor): Don't! It invokes undefined behaviour.
ยง10.4/6:
Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call (10.3) to a pure virtual function directly or indirectly for the object being created (or destroyed) from such a constructor (or destructor) is undefined.
It should work with a few syntactic modifications.
#include <iostream>
class A {
public:
virtual ~A() {}
virtual void foo() = 0;
void x() { foo(); }
};
class B: public A{
void foo(){ std::cerr << "bingo!" << std::endl; }
};
int main(){
B b;
b.x();
return 0;
}
$ g++ -Wall -Weffc++ derived.cc
$ ./a.out
bingo!
This technique is perfectly legal.
Seems that what you are looking for is an implementation of the Template Method pattern.
You need to use pointers, in order to take advantage of polymorphism (thus avoiding the message ... x is not a member of B)
#include <iostream>
class A{
public:
virtual void foo() = 0;
virtual void x(){ foo(); }
};
class B: public A{
void foo(){ std::cout<<"this is b"<<std::endl; }
};
int main(){
A* b= new B();
b->x();
return 0;
}
Well in theory that works just as fine, you should though add a return type to foo() on class B