Multiple inheritance constructor/destructor design question

J

Joseph Turian

I have a global method "update_var(double v);", which updates the value
of global variable 'var'.
I have a class Foo, which would like to know when 'var' is updated.

Let's say I make an ABC:
class Notify {
virtual void notify_that_var_has_updated() = 0;
};

and then I use MI to make Foo inherit from Notify.
Finally, I make a global method:
notify_object(Notify* n);
that will keep track of all Notify objects that want to be told when
update_var is called.

Can I make it that constructing Notify will automatically call
'notify_object', and destructing Notify will automatically call
'denotify_object'? This will prevent dangling pointers. If so, how do I
make sure that any deriving class (e.g. Foo) will also call Notify's
constructors and destructors?
 
J

Joseph Turian

One followup question:

If I write:
Notify::Notify() {
notify_object(this);
}
and this constructor is invoked from a derived class (Foo object), then
will the 'this' pointer be valid for the derived object? i.e. will
this->notify_that_var_has_updated() do The Right Thing and invoke
Foo::notify_that_var_has_updated()?

Thanks,
Joseph
 
?

=?ISO-8859-15?Q?Juli=E1n?= Albo

Joseph said:
Can I make it that constructing Notify will automatically call
'notify_object', and destructing Notify will automatically call
'denotify_object'?

If you want to do something in the construction and some other thing in the
destruction, you just need to do it in the constructor and in the
destructor, respectively.
 
O

Ondra Holub

Joseph Turian napsal:
One followup question:

If I write:
Notify::Notify() {
notify_object(this);
}
and this constructor is invoked from a derived class (Foo object), then
will the 'this' pointer be valid for the derived object? i.e. will
this->notify_that_var_has_updated() do The Right Thing and invoke
Foo::notify_that_var_has_updated()?

Thanks,
Joseph

Yes, it will be valid. This has type Notify* and that is all, what
notify_object needs to know, because notify_that_var_has_updated is
virtual.
 
S

Sylvester Hesp

Joseph Turian said:
One followup question:

If I write:
Notify::Notify() {
notify_object(this);
}
and this constructor is invoked from a derived class (Foo object), then
will the 'this' pointer be valid for the derived object? i.e. will
this->notify_that_var_has_updated() do The Right Thing and invoke
Foo::notify_that_var_has_updated()?

Only until _after_ Foo::Foo has ran. If your notify_object() calls
notify_that_var_has_updated() through the passed pointer, this will result
in undefined behaviour because the type of the object is still merely a
Notify, not a Foo (and therefore hasn't a valid
notify_that_var_has_updated() implementation).

Regarding your earlier question:
Can I make it that constructing Notify will automatically call
'notify_object', and destructing Notify will automatically call
'denotify_object'? This will prevent dangling pointers. If so, how do I
make sure that any deriving class (e.g. Foo) will also call Notify's
constructors and destructors?

A derived class _always_ calls a ctor and dtor of the base class if they
exist (whether they're auto-generated or not). If you don't specify a base
ctor in the initializer list of the derived ctor, the default ctor of the
base is invoked. So yes, you can safely do what you want to do (but keep in
mind my earlier statement about calling virtual functions during
construction) :).

- Sylvester
 
G

Grizlyk

Joseph said:
Notify::Notify() {
notify_object(this);
}
and this constructor is invoked from a derived class (Foo object), then
will the 'this' pointer be valid for the derived object? i.e. will
this->notify_that_var_has_updated() do The Right Thing and invoke
Foo::notify_that_var_has_updated()?

If you are mix Notify() as MI in one place in base class, all derived
can overload the method as in ordinary inheritance and if the method is
virtual, correct "this" adjustment will be done (if needed)
automaticaly, so your overloaded Foo::notify_that_var_has_updated()
will get correct "this" of "Foo" class.

The trouble in MI only if you want to do reinterprete_cast<> from base
to derived, it can be failed without dynamic_cast<>.

Take example :)

#include <stdio.h>

class Base;
static Base *p=0;

class Base
{
int a;
public:
virtual void method(){ printf("%p: Base::method\n",this); }
Base(){ printf("%p: Base::\n",this); p=this;}
};

class Base2
{
int a;
public:
virtual void method2(){ printf("%p: Base::method2\n",this); }
Base2(){ printf("%p: Base2::\n",this); }
};

class Derived: public Base2, public Base
{
public:
void method(){ printf("%p: Derived::method\n",this); }
Derived(){ printf("%p: Derived::\n",this); }
};

int main()
{
Derived d;

p->method();
p->Base::method();
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top