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.
Related
I know we better don't call a virtual function in the constructor since the derived class construction not started yet based on https://isocpp.org/wiki/faq/strange-inheritance#calling-virtuals-from-ctors , but what's going on if we call a non-virtual function in constructor, but the non-virtual function call a virtual one, is it dangerous as well?
If YES, then how can we avoid it, if the call stack for a non-virtual is more deep, we cannot be aware of this issue, right?
class A
{
public:
A()
{
funcA();
}
void funcA()
{
func1();
}
virtual void func1(){
std::cout << "A func1" <<std::endl;
}
};
class B : public A
{
public:
B()
{
}
virtual void func1(){
std::cout << "B func1" <<std::endl;
}
};
if we call a non-virtual function in constructor, but the non-virtual function call a virtual one, is it dangerous as well?
Yes. Take this example:
struct foo {
foo() { proxy(); }
void proxy() { call(); }
virtual void call() = 0;
};
struct bar : foo {
void call() override {}
};
Instantiating bar will most likely result in a runtime fault. It may print something like "pure virtual method called" and die.
how can we avoid it, if the call stack for a non-virtual is more deep, we cannot be aware of this issue, right?
Not without analysing the code. You may find a static analyzer that is capable of catching this - or you'll have to do it manually.
The following code is based on the example on page 298 of C++ Templates: the Complete Guide. I removed the parts not relevant to my question.
class Virtual {
public:
virtual void foo() {
}
};
class Base : private Virtual {
public:
void foo() {
std::cout << "Base::foo()" << '\n';
}
};
class Derived : public Base {
public:
void foo() {
std::cout << "Derived::foo()" << '\n';
}
};
int main()
{
Base *p = new Derived;
p->foo(); // calls Derived::foo()
}
I do not understand how the call p->foo() ends up calling Derived::foo. More concretely, the static type of p is Base*. Base::foo is non-virtual. Now, Base privately inherits from 'Virtual', which has its own foo and it looks as if Base::foo somehow gets the virtual specifier from Virtual::foo. What is actually going on here?
The virtualness of foo is inherited from the base class Virtual.
In fact, writing virtual in Derived::foo will be superfluous and many developers will omit it. You cannot undo virtualness once you've marked that function as virtual in a base class.
You can force a call of Base::foo by writing p->Base::foo(); but that's an ugly contrivance.
Here is the code:
#include <iostream>
class A
{
public:
void foo()
{
cout<<"this is base foo()"<<endl;
}
void callfoo()
{
foo();
}
};
class B: public A
{
public:
void foo()
{
cout<<"this is child foo()"<<endl;
}
};
int main()
{
B b;
b.callfoo(); //Output: "this is base foo()"
b.foo(); //Output: "this is child foo()"
return 0;
}
Now when I call b.callfoo(), instead of calling the foo() of child class B, callfoo() calls foo() of base class A. In class B we have overridden foo() with a new implementation, but still callfoo() is calling the base foo() instead of the child foo(). Please help if you have any explanation for this behaviour.
In C++, you need to explicitly mark methods as overridable by adding the virtual keyword: virtual void foo().
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?
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