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
Related
I have been watching several videos, and I have come to know how virtual function calls are processed through late binding.
In early binding, for lines like ptr->func(...), the compiler reviews the data type for ptr and looks in the corresponding class for the func(...) definition.
While during late binding for virtual functions, ptr address is accessed, and then the definition is looked up in the corresponding class.
If I am right about the mechanism I have just mentioned, then why does the following code produce an error?
class A{
public:
void func(){
}
};
class B: public A{
public:
virtual void f4(){
cout<<"Cunt"<<endl;
}
};
int main(){
A* ptr;
B obj;
ptr=&obj;
ptr->f4();
return 0;
}
Also, why does the below code produce the output base instead of the output derived?
class A{
public:
void f4(){
cout<<"base"<<endl;
}
};
class B: public A{
public:
virtual void f4(){
cout<<"derived"<<endl;
}
};
int main(){
A* ptr;
B obj;
ptr=&obj;
ptr->f4();
return 0;
}
Please help. Am I wrong about the mechanism?
In class A, the function f4 should be defined as virtual too:
class A {
public:
virtual void f4(){
std::cout << "base" << std::endl;
}
};
In your case, f4 is non-virtual function, due to non-virtual inheritance.
One more thing, derived virtual functions should be mark as override, and the virtual is not necessary:
class B : public A {
public:
void f4() override {
std::cout << "derived" << std::endl;
}
};
If you would try to mark f4 in B as override without making it virtual in A first, you would get the compilation error: error: ‘virtual void B::f4()’ marked ‘override’, but does not override- which means that you won't be able to access it using A class pointer.
Side note: read the following post: Why is "using namespace std;" considered bad practice?
In your first example, A does not have a method named f4(), so the call to ptr->f4() is not valid.
In your second example, A::f4() is not marked as virtual, so the call to ptr->f4() does not perform virtual dispatch, and so calls A::f4() rather than B::f4().
The solution to both problems is the same - make f4() be virtual in A, and have B override it, eg:
class A{
public:
virtual void f4() {
cout << "base" << endl;
}
};
class B: public A{
public:
void f4() override {
cout << "derived" << endl;
}
};
int main(){
A* ptr;
B obj;
ptr = &obj;
ptr->f4();
return 0;
}
Can I have a virtual function in the base class and some of my derived classes do have that function and some don't have.
class A{
virtual void Dosomething();
};
class B : public A{
void Dosomething();
};
class C : public A{
//Does not have Dosomething() function.
};
From one of my c++ textbook:
Once a function is declared virtual, it remains virtual all the way down the inheritance, even if the function is not explicitly declared virtual when the derived class overrides it.
When the derived class chooses not to override it, it simply inherits its base class's virtual function.
Therefore to your question the answer is No. Class c will use Class A's virtual function.
Derived classes do not have to implement all the virtual functions, unless it is a pure virtual function. Even in this case, it will cause an error only when you try to instantiate the derived class( without implementing the pure virtual function ).
#include <iostream>
class A{
public :
virtual void foo() = 0;
};
class B: public A{
public :
void foo(){ std::cout << "foo" << std::endl;}
};
class C: public A{
void bar();
};
int main() {
//C temp; The compiler will complain only if this is initialized without
// implementing foo in the derived class C
return 0;
}
I think the closest you might get, is to change the access modifier in the derived class, as depicted below.
But, I would consider it bad practice, as it violates Liskov's substitution principle.
If you have a situation like this, you might need to reconsider your class design.
#include <iostream>
class A {
public:
virtual void doSomething() { std::cout << "A" << std::endl; }
};
class B : public A {
public:
void doSomething() override { std::cout << "B" << std::endl; };
};
class C : public A {
private:
void doSomething() override { std::cout << "C" << std::endl; };
};
int main(int argc, char **args) {
A a;
a.doSomething();
B b;
b.doSomething();
C c;
//c.doSomething(); // Not part of the public interface. Violates Liskov's substitution principle.
A* c2 = &c;
c2->doSomething(); // Still possible, even though it is private! But, C::doSomething() is called!
return 0;
}
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 a problem in properly handling method overriding where an abstract class is present
inside my classes hierarchy.
I'll try to explain:
class AbstractClass{
public:
virtual void anyMethod() = 0;
};
class A : public AbstractClass {
void anyMethod() {
// A implementation of anyMethod
cout << "A";
}
};
class B : public AbstractClass {
void anyMethod() {
// B implementation of anyMethod
cout << "B";
}
};
AbstractClass *ptrA, *ptrB;
ptrA = new A();
ptrB = new B();
ptrA->anyMethod(); //prints A
ptrB->anyMethod(); //prints B
Ok..previous example work fine .. the concrete implementation of the AbstractClass
method anyMethod will be called at run time.
But AbstractClass is derived from another base class which has a method not virtual
called anyMethod:
class OtherClass {
public:
void anyMethod() {
cout << "OtherClass";
}
};
class AbstractClass : public OtherClass {
public:
virtual void anyMethod() = 0;
};
//A and B declared the same way as described before.
Now , if i try something like that:
ptrA = new A();
ptrB = new B();
ptrA->anyMethod(); //prints OtherClass
ptrB->anyMethod(); //prints OtherClass
What am I misunderstanding?
Is there any solution for making ptrA and ptrB printing A and B without using cast, typeid, etc?
Why don't you do:
class OtherClass
{
public:
virtual void anyMethod()
{
cout << "OtherClass";
};
}
That should solve your problems
If anyMethod was declared virtual in the base class to which you have a pointer or reference, it should be looked up virtually and print A and B correctly. If it wasn't, then there is nothing you can do (beyond changing it to be virtual).
I think that if the method in OtherClass that you want to override in A and B is NOT virtual, then the override is not implicit.
I believe there's a way to Explicitly override the functions, look that up.
DeadMGs answer is of course correct. But, if you cannot change OtherClass Methode (e.g. it's from a third party lib) you might want to try this:
Are the pointers ptrA and ptrB of type OtherClass or AbstractClass in your lower example?
If they are OtherClass I would expect the behaviour you described. You could try casting the pointer to AbstractClass then:
dynamic_cast<AbstractClass*>(ptrA)->anyMethod();
As far as I can see from your code OtherClass::anyMethod() is not a virtual and already implemented. It should work as you described if you define it as virtual
I think that your declaration for the second case is:
OtherClass* ptrA; and not AbstractClass *ptrA;
if you declared like the first case , there's no problem because the method is virtual,but if you declare as OtherClass , the compiler will not find virtual and bind to the adress of this method without using vtble.
thanks for the answers.. helped me a lot to understand the problem.
In effect I posted some wrong code, because i was misunderstanding the real problem.
Anyway, i think i partially solved my problem.
Here's the code:
#include <iostream>
`` using namespace std;
class Other{
public:
void foo(){
cout << "Other\n";
}
void foo(int a){}
};
class Abstract : public Other{
public:
virtual void foo() {};
virtual void foo(int c){
Other::foo(c);
}
};
class A : public Abstract{
public:
void foo(){
cout << "A\n";
}
};
class B : public Abstract{
public:
void foo(){
cout << "B\n";
}
};
int main(){
cout << "main\n";
Abstract * ptrA = new A();
Abstract * ptrB = new B();
Other *o = new Other();
o->foo();
ptrA->foo();
ptrB->foo();
ptrB->foo(3); //can't no more use the method foo with different signatures implemented in the base class Other, unless I explicitly redefined in the class Abstract
dynamic_cast<Other*>(ptrB)->foo(3);//can't dynamic_cast from derived to base
I was making two errors:
In my real code (not the simplified version posted before) i forgot to declare virtual
the function foo()
Even declaring virtual wasn't enough. In fact all the implementations of that function must be wrapped inside the class Abstract to become visible to the subclasses A and b. Otherwise wont't compile.
I don't know if it could be a clean solution..in fact that way I need to wrap all foo method signatures.
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?