BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Virtual Templatized Method
Goto page 1, 2  Next
 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (Language C++)
View previous topic :: View next topic  
Author Message
tinyabs
Guest





PostPosted: Sun Aug 28, 2005 3:33 pm    Post subject: Virtual Templatized Method Reply with quote



Please look at the simple code below.

template<class T>
class Handle
{
protected:
// called by destructor
virtual void Close(){...}
virtual ~Handle() { Close(); }
};

class Monitor : public Handle<LPCRITICAL_SECTION>
{
protected:
// by right should be called when Monitor object destroy
void Close() {...}
};

The test code is this.
{
Monitor monitor(new CRITICAL_SECTION);
}

When monitor object exit the scope, Handle<T>::Close() is called instead of
Monitor::Close(). How do I let Monitor::Close() be called instead?



Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Sun Aug 28, 2005 7:33 pm    Post subject: Re: Virtual Templatized Method Reply with quote




"tinyabs" <nospam (AT) me (DOT) com> wrote


Quote:
virtual void Close(){...}
virtual ~Handle() { Close(); }

That will not work. A base class destructor cannot call a virtual method
that is overridden in a descenant class. By the time the base class
destructor is called, the descendant class no longer exists an cannot be
accessed.

Your descendant class must provide its own destructor that calls Close()
directly.

Quote:
class Monitor : public Handle<LPCRITICAL_SECTION
{
protected:
// by right should be called when Monitor object destroy
void Close() {...}

No, it should not. Not with the code you have shown.

Quote:
When monitor object exit the scope, Handle of Monitor::Close().

Correct. That is how virtual destructors work.

Quote:
How do I let Monitor::Close() be called instead?

You cannot. Not from Handle<T> anyway. The only way is for Monitor to
declare its own destructor, ie:

template< class T >
class Handle
{
protected:
virtual void Close() = 0;
public:
virtual ~Handle() {}
};

class Monitor : public Handle<LPCRITICAL_SECTION>
{
protected:
virtual void Close() {...}
public:
virtual ~Monitor() { Close(); }
};


Gambit



Back to top
tinyabs
Guest





PostPosted: Sun Aug 28, 2005 8:22 pm    Post subject: Re: Virtual Templatized Method Reply with quote



Thanks. I understood now.


Back to top
Alan Bellingham
Guest





PostPosted: Sun Aug 28, 2005 10:32 pm    Post subject: Re: Virtual Templatized Method Reply with quote

"tinyabs" <nospam (AT) me (DOT) com> wrote:

Quote:
Please look at the simple code below.

template<class T
class Handle
{
protected:
// called by destructor
virtual void Close(){...}
virtual ~Handle() { Close(); }
};

class Monitor : public Handle {
protected:
// by right should be called when Monitor object destroy
void Close() {...}
};

Ah, grasshopper. You have missed the essence of the C++ object model.

Base objects are constructed before derived objects, and destroyed after
the derived objects are destroyed.

Within a destructor, the type of the object being destroyed is _that of
the destructor_, not of whatever the final object had been.

Hence, Handle
Quote:
The test code is this.
{
Monitor monitor(new CRITICAL_SECTION);
}

When monitor object exit the scope, Handle<T>::Close() is called instead of
Monitor::Close(). How do I let Monitor::Close() be called instead?

You call the Close() method within ~Monitor().

BTW - within a constructor, the type of object being constructed is also
that of the constructor.

This is why you may get a pure virtual function call happening. It's
almost always down to a constructor or destructor initialing the call.
Alan Bellingham
--
Me <url:mailto:alanb (AT) episys (DOT) com> <url:http://www.doughnut.demon.co.uk/>
ACCU - C, C++ and Java programming <url:http://accu.org/>
The 2004 Discworld Convention <url:http://dwcon.org/>

Back to top
tinyabs
Guest





PostPosted: Mon Aug 29, 2005 1:45 am    Post subject: Re: Virtual Templatized Method Reply with quote


"Alan Bellingham" <alanb (AT) episys (DOT) com> wrote

Quote:
"tinyabs" <nospam (AT) me (DOT) com> wrote:
You have missed the essence of the C++ object model.
C++ was one of the best experiences I had. I'm spending lots of time to

learn.

Quote:

Base objects are constructed before derived objects, and destroyed after
the derived objects are destroyed.
What's the difference between a virtual and a non-virtual destructor?

Whether virtual or not, it seems to have same calling sequence.

Quote:

Within a destructor, the type of the object being destroyed is _that of
the destructor_, not of whatever the final object had been.

Hence, Handle<T>::Close() will be called.

if I convert it to Handle<T> *, will the derived class virtual method be

called? I had <Class> * objects and derived class's virtual method are
called this way.

Quote:
When monitor object exit the scope, Handle<T>::Close() is called instead
of
Monitor::Close(). How do I let Monitor::Close() be called instead?

You call the Close() method within ~Monitor().

BTW - within a constructor, the type of object being constructed is also
that of the constructor.

Are you saying a derived class is a object inside the base class,

technically? And they are classes of their own, semantically in
compartments.




Back to top
Alisdair Meredith[TeamB]
Guest





PostPosted: Mon Aug 29, 2005 4:54 am    Post subject: Re: Virtual Templatized Method Reply with quote

tinyabs wrote:

Quote:
What's the difference between a virtual and a non-virtual destructor?
Whether virtual or not, it seems to have same calling sequence.

That's a good queston <g>

The difference is seen when you call delete on a pointer to an object.

Try the following simple example:


#include <iostream>
#include <ostream>

struct base
{
base()
{
std::cout << "constructing base" << std::endl;
Test();
}

virtual ~base()
{
Test();
std::cout << "destroying base" << std::endl;
}

virtual void Test()
{
std::cout << "testing base" << std::endl;
}
};

struct derived : base
{
derived() : base()
{
}

virtual ~derived()
{
std::cout << "destroying derived" << std::endl;
}

virtual void Test()
{
std::cout << "testing derived" << std::endl;
}
};

int main()
{
base * pBase = new derived();
std::cout << std::endl;

pBase->Test();
std::cout << std::endl;

delete pBase;
}



When you run this code, you will see that the call to Test from outside
the constructor/destructor is dispatched 'dynamically' calling the
derived version. However, the calls to Test from the
constructor/destructor are dispatched 'statically' and call the version
for the class being constructed/destroyed.

Likewise, although we have a pointer to a base object, when we call
delete it is the derived constructor that is called - because the
destructor is virtual.

Try the same example but remove the virtual keyword from the base
constructor, and you will see the derived destructor is not called. In
this example the effect is not too bad, but imagine if derived
introduced members or state of its own, such as holding onto a database
transaction on a remote server. These resources would never be
released.

AlisdairM(TeamB)

Back to top
tinyabs
Guest





PostPosted: Mon Aug 29, 2005 7:20 am    Post subject: Re: Virtual Templatized Method Reply with quote

Quote:
When you run this code, you will see that the call to Test from outside
the constructor/destructor is dispatched 'dynamically' calling the
derived version. However, the calls to Test from the
constructor/destructor are dispatched 'statically' and call the version
for the class being constructed/destroyed.

I know there's a VMT in each pointer and derived virtual methods are invoked
instead of base classes'. But does a non-pointer(what do u call it anyway?)
uses VMT or not? Do I really have to use pointer to get derived method to
call the way I wanted?



Back to top
Hendrik Schober
Guest





PostPosted: Mon Aug 29, 2005 7:55 am    Post subject: Re: Virtual Templatized Method Reply with quote

tinyabs <nospam (AT) me (DOT) com> wrote:
Quote:
When you run this code, you will see that the call to Test from outside
the constructor/destructor is dispatched 'dynamically' calling the
derived version. However, the calls to Test from the
constructor/destructor are dispatched 'statically' and call the version
for the class being constructed/destroyed.

I know there's a VMT in each pointer and derived virtual methods are invoked
instead of base classes'. But does a non-pointer(what do u call it anyway?)
uses VMT or not? Do I really have to use pointer to get derived method to
call the way I wanted?


What you mean is whether functions are called
polymorphicaly (i.e. which function to call
is figured out at run-time) or directly. The
former is only in place when, at run-time, it
is unknown which type the object has. If you
have

Derived d;
d.f();

the type is well-known. If, OTOH, you have a
pointer or a reference to a base class, the
type isn't know -- the might be an instance
of some derived class behind the ptr/ref:

Base& rb = d;
Base* pb = &d;
rb.f();
pb->f();

In this case, if 'Base::f()' is virtual, it's
called through the VMT.

HTH,

Schobi

--
[email]SpamTrap (AT) gmx (DOT) de[/email] is never read
I'm Schobi at suespammers dot org

"Coming back to where you started is not the same as never leaving"
Terry Pratchett



Back to top
Hendrik Schober
Guest





PostPosted: Mon Aug 29, 2005 8:02 am    Post subject: Re: Virtual Templatized Method Reply with quote

tinyabs <nospam (AT) me (DOT) com> wrote:
Quote:
[...]
BTW - within a constructor, the type of object being constructed is also
that of the constructor.

Are you saying a derived class is a object inside the base class,
technically? And they are classes of their own, semantically in
compartments.


No. He said that the dynamic type of object,
during construction/destruction of the base
class, is the type of the base class, because
at that time, the object of the derived class
is either not yet constructed (derived class
ctors are called after base class ctors) or
no longer existing (derived class dtors are
called before base class dtors).
You don't need to memorize this, BTW, as it
is very logically: When inside of a derived
class' ctor, you expect to have the base
class parts of the object fully constructed.
For example:

class Base {
// ...
X* p;
};

class Derived {
// ...
};

When inside 'Derived::Derived()', you expect
'Base::p' to be initialized by 'Base::Base()'.
So 'Base::Base()' has to be called before
'Derived::Derived()'. Once you figured out
this, just remember that dtors are called in
the opposite order.

Schobi

--
[email]SpamTrap (AT) gmx (DOT) de[/email] is never read
I'm Schobi at suespammers dot org

"Coming back to where you started is not the same as never leaving"
Terry Pratchett



Back to top
Alan Bellingham
Guest





PostPosted: Mon Aug 29, 2005 9:49 am    Post subject: Re: Virtual Templatized Method Reply with quote

"tinyabs" <nospam (AT) me (DOT) com> wrote:

Quote:
Base objects are constructed before derived objects, and destroyed after
the derived objects are destroyed.

What's the difference between a virtual and a non-virtual destructor?
Whether virtual or not, it seems to have same calling sequence.

The difference between a virtual and a non-virtual destructor is that,
given a pointer to base, "delete base;" will call the derived destructor
if and only if it is a virtual destructor.

Quote:
Within a destructor, the type of the object being destroyed is _that of
the destructor_, not of whatever the final object had been.

Hence, Handle<T>::Close() will be called.

if I convert it to Handle<T> *, will the derived class virtual method be
called? I had <Class> * objects and derived class's virtual method are
called this way.

The derived class destructor will be called. But it was being called
any, since it is virtual. However, it is in the base class destructor
that the call to Close() is made, and that is after the derived class no
longer exists.

Quote:
Are you saying a derived class is a object inside the base class,
technically? And they are classes of their own, semantically in
compartments.

The other way around.

Technically speaking, the base class is a sub-object of the derived
object. During construction of an object, all subobjects are constructed
first. This means all base classes, and all member objects.
Alan Bellingham
--
Me <url:mailto:alanb (AT) episys (DOT) com> <url:http://www.doughnut.demon.co.uk/>
ACCU - C, C++ and Java programming <url:http://accu.org/>
The 2004 Discworld Convention <url:http://dwcon.org/>

Back to top
tinyabs
Guest





PostPosted: Mon Aug 29, 2005 12:44 pm    Post subject: Re: Virtual Templatized Method Reply with quote

Quote:
No. He said that the dynamic type of object,
during construction/destruction of the base
class, is the type of the base class, because
at that time, the object of the derived class
is either not yet constructed (derived class
ctors are called after base class ctors) or
no longer existing (derived class dtors are
called before base class dtors).
You don't need to memorize this, BTW, as it
is very logically: When inside of a derived
class' ctor, you expect to have the base
class parts of the object fully constructed.

So obviously, I can't call a derived method in base method or access a
private scope derived variable from base class. They are actually in
compartments.

Thanks guys.



Back to top
Hendrik Schober
Guest





PostPosted: Mon Aug 29, 2005 12:51 pm    Post subject: Re: Virtual Templatized Method Reply with quote

tinyabs <nospam (AT) me (DOT) com> wrote:
Quote:
No. He said that the dynamic type of object,
during construction/destruction of the base
class, is the type of the base class, because
at that time, the object of the derived class
is either not yet constructed (derived class
ctors are called after base class ctors) or
no longer existing (derived class dtors are
called before base class dtors).
You don't need to memorize this, BTW, as it
is very logically: When inside of a derived
class' ctor, you expect to have the base
class parts of the object fully constructed.

So obviously, I can't call a derived method in base method or access a
private scope derived variable from base class. [...]

Yes, you can. You only cannot during the
construction/destruction of the base object.

Quote:
Thanks guys.

Schobi

--
[email]SpamTrap (AT) gmx (DOT) de[/email] is never read
I'm Schobi at suespammers dot org

"Coming back to where you started is not the same as never leaving"
Terry Pratchett



Back to top
Chris Uzdavinis (TeamB)
Guest





PostPosted: Mon Aug 29, 2005 1:49 pm    Post subject: Re: Virtual Templatized Method Reply with quote

"tinyabs" <nospam (AT) me (DOT) com> writes:

Quote:
I know there's a VMT in each pointer

Not quite right. There is a VMT in each CLASS that has a virtual
function. Each object of such a class has an invisible pointer to its
VMT. When you call a function on a pointer whose type is polymorphic,
the runtime will dereference your pointer to find its object, pull out
the pointer to the VMT for that class, dereference that pointer to see
the table, and fetch the function pointer stored in the proper offset.

Quote:
and derived virtual methods are invoked instead of base
classes'.

Whatever function is in the class's VTBL (VMT) is used. Normally a
derived class gets an exact copy from its base class, unless it
overrides a function. Then the overridden function replaces the base
pointer in the table. For functions not overridden, the base version
is called, and for new virtual functions, the derived class's VTBL is
expanded.

Quote:
But does a non-pointer(what do u call it anyway?) uses VMT or not?

A reference to an object uses the virtual lookup mechanism, but
calling directly on an object does not, since the object already is
the most derived type and thus there is no need to lookup the virtual
function in the VTBL.

Quote:
Do I really have to use pointer to get derived method to call the
way I wanted?

You can use a pointer or reference. But, be sure that the pointer
points to a valid object! If you're in the destructor of a base
class, don't downcast it to call a derived function, because the
derived part has already been destroyed and the program will have
undefined behavior.

--
Chris (TeamB);

Back to top
tinyabs
Guest





PostPosted: Tue Aug 30, 2005 6:40 am    Post subject: Re: Virtual Templatized Method Reply with quote

----------------------------- library
code ------------------------------------
template<class T>
class Handle
{
protected:
struct HandleRef
{
T Handle;
int RefCount;
};
HandleRef *FRefObj;
void AddRef()
{
if (FRefObj != NULL)
++ FRefObj->RefCount;
}

void Release()
{
if (FRefObj != NULL)
{
-- FRefObj->RefCount;

if (FRefObj->RefCount == 0)
{
Close();
FRefObj->Handle = NULL;
delete FRefObj;
FRefObj = NULL;
}
}
}

virtual void Close() = 0;
public:
explicit Handle(const HANDLE handle)
{
CopyNew(handle);
}

Handle()
{
FRefObj = NULL;
}
Handle(const Handle &handle)
{
Copy(handle);
}

virtual ~Handle()
{
Release();
}

void Copy(const Handle &handle)
{
Release();
FRefObj = handle.FRefObj;
AddRef();
}

void CopyNew(T &handle)
{
FRefObj = new HandleRef;
FRefObj->Handle = handle;
FRefObj->RefCount = 1;
}

void Reset(T handle = NULL)
{
Release();
if (handle != NULL)
{
CopyNew(handle);
} else
FRefObj = NULL;
}

T Get() const
{
return FRefObj->Handle;
}
Handle &operator=(Handle &handle)
{
Copy(handle);
}

operator T() const
{
return FRefObj->Handle;
}
private:

};


class Monitor : public Handle<LPCRITICAL_SECTION>
{
public:
Monitor();
Monitor(const Monitor &monitor);
~Monitor();
void Enter();
bool TryEnter();
void Leave();
Monitor &operator=(Monitor &monitor);
protected:
void Close();
private:
};

-------------------- Demo Code------------------------

{
Monitor monitor;
}

Any alternative to get Monitor::Close() called?


"Chris Uzdavinis (TeamB)" <chris (AT) uzdavinis (DOT) com> wrote

Quote:
"tinyabs" <nospam (AT) me (DOT) com> writes:

I know there's a VMT in each pointer

Not quite right. There is a VMT in each CLASS that has a virtual
function. Each object of such a class has an invisible pointer to its
VMT. When you call a function on a pointer whose type is polymorphic,
the runtime will dereference your pointer to find its object, pull out
the pointer to the VMT for that class, dereference that pointer to see
the table, and fetch the function pointer stored in the proper offset.

and derived virtual methods are invoked instead of base
classes'.

Whatever function is in the class's VTBL (VMT) is used. Normally a
derived class gets an exact copy from its base class, unless it
overrides a function. Then the overridden function replaces the base
pointer in the table. For functions not overridden, the base version
is called, and for new virtual functions, the derived class's VTBL is
expanded.

But does a non-pointer(what do u call it anyway?) uses VMT or not?

A reference to an object uses the virtual lookup mechanism, but
calling directly on an object does not, since the object already is
the most derived type and thus there is no need to lookup the virtual
function in the VTBL.

Do I really have to use pointer to get derived method to call the
way I wanted?

You can use a pointer or reference. But, be sure that the pointer
points to a valid object! If you're in the destructor of a base
class, don't downcast it to call a derived function, because the
derived part has already been destroyed and the program will have
undefined behavior.

--
Chris (TeamB);



Back to top
Chris Uzdavinis (TeamB)
Guest





PostPosted: Tue Aug 30, 2005 1:10 pm    Post subject: Re: Virtual Templatized Method Reply with quote

"tinyabs" <nospam (AT) me (DOT) com> writes:

Quote:
Any alternative to get Monitor::Close() called?

The way to accomplish that is to call it from Monitor::~Monitor();

--
Chris (TeamB);

Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (Language C++) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.