Page 1 of 1
A Tad Off - Virtual Functions and their Kin
Posted: Mon Dec 10, 2007 10:54 pm
by Alboin
I think I've done this before. I really do. I'm not sure what's wrong with me. I really don't.
I have a class, D, that has a virtual function f. D, in it's constructor, calls f.
E is a class derived from D. It implements f.
D is not apparently calling E::f, but D::f, which gets me a 'pure virtual method called' error.
Anyone? I'm feeling that D doesn't 'see' E, in a sense, and therefore calls its own version. Is there a way around this?
Thanks!
Code: Select all
#include <iostream>
using namespace std;
class D {
virtual void vfc() { }
public:
D() {
vfc();
}
};
class E : public D {
void vfc() {
cout << "Hello" << endl;
}
};
int main() {
E k;
}
Posted: Tue Dec 11, 2007 12:42 am
by Colonel Kernel
No. Do not call virtual methods in the constructor. While D's constructor is running, the object's vptr is pointing to D's v-table, not E's. Weird things will happen.
What are you trying to accomplish at a higher level?
Posted: Tue Dec 11, 2007 5:41 am
by Alboin
Colonel Kernel wrote:What are you trying to accomplish at a higher level?
I'm abstracting a GTK treeview so I can create new treeview types by just creating children of this class, and implementing certain handlers. (eg. clicked, dragged, etc.) The handlers are the virtual functions.
Posted: Tue Dec 11, 2007 8:33 am
by Colonel Kernel
Why do those handlers need to be called from the constructor?
One way to get around this problem is to have the base class call the handlers from a virtual "init" method that gets called after construction (two-phase initialization). If you don't want to have to remember to call "init" every time you create a new instance, you can wrap that sequence up in a factory method.
Code: Select all
class MyTreeView: public BaseTreeView {...};
std::auto_ptr<BaseTreeView> createTreeView()
{
std::auto_ptr<BaseTreeView> tv( new MyTreeView() );
tv->init();
return tv;
}
Posted: Tue Dec 11, 2007 3:25 pm
by Alboin
Hey, thanks. The two-phase constructor did it for me.
Why do those handlers need to be called from the constructor?
There's a handler called 'create' that adds rows to the tree during it's creation.
Posted: Wed Dec 12, 2007 2:04 am
by Solar
Colonel Kernel wrote:Albion wrote:I have a class, D, that has a virtual function f. D, in it's constructor, calls f.
E is a class derived from D. It implements f.
D is not apparently calling E::f, but D::f, which gets me a 'pure virtual method called' error.
No. Do not call virtual methods in the constructor. While D's constructor is running, the object's vptr is pointing to D's v-table, not E's. Weird things will happen.
Worse:
E's constructor will not even start running before
D's constructor is finished - as every child class consists of "base class plus X". Even
if the vptr would be pointing at the right place, you'd attempt to call a member function of a not-completely-initialized object.