views:

102

answers:

4

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?

+1  A: 

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.

baol
+3  A: 

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.

Georg Fritzsche
I like the virtual destructor touch :)
baol
I am trying to create a class that must have a "DeleteItens" as a abstract function that will be called inside the Base class's destructor. But I am still getting the undefined reference =[
Jonathan
@Jonathan: it seems you asked the wrong question :)
baol
@Jonathan: Can you update the question with an example that exhibits the problem or ask a question specifically about the problem you are having?
Georg Fritzsche
I updated the question, does it help you understand me? I lack some english =[
Jonathan
what a weird thing isn't it. I just added it inside other function and it at least compiled, now I am going to test... But still, weird. Thanks for the answer
Jonathan
See the update i added, that should clarify it. The main problem is - what do you expect it to do from the base' constructor? Calling into the derived class isn't useful, its destructor gets invoked before the base class' destructor.
Georg Fritzsche
yeah, it compiles but does not run... I guess I will have to find other way around. Sometimes I find C++ so weird. I like it the best, but there are somethings that doesn't make much sense to me... Of course, my knowledge is very little close to who created the logic of it, but as a programmer I try to aways understand the logic behind stuff
Jonathan
now it made sense, thanks gf
Jonathan
If you want to understand it better, e.g. C++ FAQ lite has some treatment of virtual functions: http://www.parashift.com/c++-faq-lite/virtual-functions.html
Georg Fritzsche
+1  A: 

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;
 }   
Tom
x() is a member of B. It is inherited publicly from A.
Ben Voigt
A: 

Well in theory that works just as fine, you should though add a return type to foo() on class B

Ricardo Ferreira