473,385 Members | 1,606 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

copy constructor clarification

Rob
I've just started writing managed C++ (VS 2005 Beta 2) and I really have not
read a whole lot about the differences between managed and unmanaged C++.

Using the class wizard, I can create a managed class defined like:
ref class MyClass {
public
MyClass(void);
~MyClas(void);
};

I'd like to know whether I should add copy and assignment constructors. The
standard syntax of
MyClass(const MyClass&);
MyClass& operator=(const MyClass&);
doesn't work. (compiler error C3699). Do I replace & with ^ ? I would think
that there's times when the default copy constructor will be insufficient.
Part of my confusion stems from my inability to understand the difference
between new and gcnew. When would I want to use one as opposed to the other?

Thanks for any pointers (no pun intended).
Nov 17 '05 #1
19 1366

--
Kapil Khosla, Visual C++ Team
This posting is provided AS IS with no warranties, and confers no rights
"Rob" wrote:
I've just started writing managed C++ (VS 2005 Beta 2) and I really have not
read a whole lot about the differences between managed and unmanaged C++.

Using the class wizard, I can create a managed class defined like:
ref class MyClass {
public
MyClass(void);
~MyClas(void);
};

I'd like to know whether I should add copy and assignment constructors. The
standard syntax of
MyClass(const MyClass&);
MyClass& operator=(const MyClass&);
doesn't work. (compiler error C3699). Do I replace & with ^ ?
The equivalent code would be

ref class MyClass {
public:
MyClass(void);
~MyClass(void);
MyClass(MyClass%);
MyClass% operator=(const MyClass%);
};

Think of the operator equivalence for definitions like this:
& = %
* = ^

Dereferencing a ^ is still done with *, though.

I would think that there's times when the default copy constructor will be insufficient.
Part of my confusion stems from my inability to understand the difference
between new and gcnew.
When would I want to use one as opposed to the other?
You would use new to allocate memory for a native object on the native heap
and gcnew to allocate memory for a manged object on the managed heap. You
can read more on gcnew on
http://msdn2.microsoft.com/library/t...us,vs.80).aspx

Thanks,
Kapil
Thanks for any pointers (no pun intended).

Nov 17 '05 #2
Rob wrote:
I've just started writing managed C++ (VS 2005 Beta 2)
It is not "managed extensions" but C++/CLI.

and I really have not
read a whole lot about the differences between managed and unmanaged C++.

Using the class wizard, I can create a managed class defined like:
ref class MyClass {
public
MyClass(void);
~MyClas(void);
};

I'd like to know whether I should add copy and assignment constructors. The
standard syntax of
MyClass(const MyClass&);
MyClass& operator=(const MyClass&);
doesn't work. (compiler error C3699). Do I replace & with ^ ?

Tracking references are denoted by % and work for both managed and native types. Also you
can define assignment operator like this, but this will work only for C++, and if you use
that type in another language you will have problems.
The managed assignment operator (that is for managed types only) is defined in C++/CLI as
a static member function with two arguments.
You may download the latest C++/CLI draft (currently 1.12) from here:

http://www.plumhall.com/ecma/index.html
I would think
that there's times when the default copy constructor will be insufficient.
Part of my confusion stems from my inability to understand the difference
between new and gcnew. When would I want to use one as opposed to the other?

Thanks for any pointers (no pun intended).

You may check this:

http://www23.brinkster.com/noicys/cppcli.htm
Nov 17 '05 #3
Rob
Question below...

"Ioannis Vranos" wrote:
Rob wrote:
I'd like to know whether I should add copy and assignment constructors. The
standard syntax of
MyClass(const MyClass&);
MyClass& operator=(const MyClass&);
doesn't work. (compiler error C3699). Do I replace & with ^ ?

Tracking references are denoted by % and work for both managed and native types. Also you
can define assignment operator like this, but this will work only for C++, and if you use
that type in another language you will have problems.
The managed assignment operator (that is for managed types only) is defined in C++/CLI as
a static member function with two arguments.


So are you saying that I shouldn't define it as
MyClass% operator=(const MyClass%);
because of language interoperability problems but rather as what? Is this it?
void operator=(MyClass%, const MyClass%); ?

I will take a look at the 300 page C++/CLI spec, but I feel that Microsoft's
documentation on managed code development in C++ could be a little clearer.

Thanks.

You may download the latest C++/CLI draft (currently 1.12) from here:

http://www.plumhall.com/ecma/index.html

Nov 17 '05 #4
Rob wrote:
So are you saying that I shouldn't define it as
MyClass% operator=(const MyClass%);
because of language interoperability problems but rather as what? Is this it?
void operator=(MyClass%, const MyClass%); ?

Well yes, if you intend to share your code with other languages (e.g. making a managed
dll). Otherwise it is OK.
I will take a look at the 300 page C++/CLI spec, but I feel that Microsoft's
documentation on managed code development in C++ could be a little clearer.

Well, the Microsoft documentation is MSDN, and they have the VS 2005 Beta on line. Check
the following on this subject:
http://msdn2.microsoft.com/library/d...us,vs.80).aspx
and what is new in general:

http://msdn2.microsoft.com/library/x...us,vs.80).aspx
Nov 17 '05 #5
Rob wrote:

So are you saying that I shouldn't define it as
MyClass% operator=(const MyClass%);
because of language interoperability problems but rather as what? Is this it?
void operator=(MyClass%, const MyClass%); ?

ref class MyClass
{
// ...

public:
static MyClass %operator=(const MyClass %x, const MyClass %y)
{
// ...
}

// ...
};
is an example. They are similar to global function ISO C++ operator overloading. You can
also define them as global functions and member functions as usual, but these will not be
accessible from the other managed languages.
Nov 17 '05 #6
Rob
Thanks. I was well aware of msdn2.microsoft.com/library, but didn't have the
specific links you provided. I had searched that site for "copy constructor"
but did not find anything. I hadn't yet tried searching for operator=,
although that page wouldn't have shown up for that either. :-)

"Ioannis Vranos" wrote:
Rob wrote:
So are you saying that I shouldn't define it as
MyClass% operator=(const MyClass%);
because of language interoperability problems but rather as what? Is this it?
void operator=(MyClass%, const MyClass%); ?

Well yes, if you intend to share your code with other languages (e.g. making a managed
dll). Otherwise it is OK.
I will take a look at the 300 page C++/CLI spec, but I feel that Microsoft's
documentation on managed code development in C++ could be a little clearer.

Well, the Microsoft documentation is MSDN, and they have the VS 2005 Beta on line. Check
the following on this subject:
http://msdn2.microsoft.com/library/d...us,vs.80).aspx
and what is new in general:

http://msdn2.microsoft.com/library/x...us,vs.80).aspx

Nov 17 '05 #7
Rob
Actually, operator= cannot be a static member as you show below. You get
compiler error C2581 followed by C2801. In fact, binary operators such as
operator= cannot have two parameters. The first parameter is implied. See
C2804.

So, I will go back to Kapil's suggested syntax.

-Rob

"Ioannis Vranos" wrote:
Rob wrote:

So are you saying that I shouldn't define it as
MyClass% operator=(const MyClass%);
because of language interoperability problems but rather as what? Is this it?
void operator=(MyClass%, const MyClass%); ?

ref class MyClass
{
// ...

public:
static MyClass %operator=(const MyClass %x, const MyClass %y)
{
// ...
}

// ...
};
is an example. They are similar to global function ISO C++ operator overloading. You can
also define them as global functions and member functions as usual, but these will not be
accessible from the other managed languages.

Nov 17 '05 #8
Rob wrote:
Actually, operator= cannot be a static member as you show below. You get
compiler error C2581 followed by C2801. In fact, binary operators such as
operator= cannot have two parameters. The first parameter is implied. See
C2804.

C++/CLI is currently in draft and has not been finished yet. VC++ 2005 is still under
development and not everything has not been implemented yet. *So far* in the draft
C++/CLI, things are as I have described them.

Beta 1 did not support other things, but now does. And the current Beta also does not
support all current C++/CLI draft features.

Do not rely completely on the current Beta to learn C++/CLI. Let's wait C++/CLI to be
finished itself first. :-)
Nov 17 '05 #9
Rob
That's fine from the perspective of learning C++/CLI, but I'm trying to use
VS 2005 Beta 2 to write code and I would've thought that correct assignment
operator syntax would've been put into the compiler kind of early on.

Otherwise, what's the "workaround"? Only create ref classes that can be
shallow copied? I posted a separate question on the syntax I need since
making the changes as suggested by Kapil leaves a problem with member
property assignment.

-Rob

"Ioannis Vranos" wrote:
Rob wrote:
Actually, operator= cannot be a static member as you show below. You get
compiler error C2581 followed by C2801. In fact, binary operators such as
operator= cannot have two parameters. The first parameter is implied. See
C2804.

C++/CLI is currently in draft and has not been finished yet. VC++ 2005 is still under
development and not everything has not been implemented yet. *So far* in the draft
C++/CLI, things are as I have described them.

Beta 1 did not support other things, but now does. And the current Beta also does not
support all current C++/CLI draft features.

Do not rely completely on the current Beta to learn C++/CLI. Let's wait C++/CLI to be
finished itself first. :-)

Nov 17 '05 #10
Rob wrote:
That's fine from the perspective of learning C++/CLI, but I'm trying to use
VS 2005 Beta 2 to write code and I would've thought that correct assignment
operator syntax would've been put into the compiler kind of early on.

I think this should be avoided for anything else than just getting a feeling of the
upcoming C++/CLI.
Nov 17 '05 #11
Rob
Well that's too bad. The Microsoft people I've spoken with claimed that I
could be pretty confident in using it to write code 1) that works and 2) that
wouldn't need to be rewritten when this thing finally ships.

"Ioannis Vranos" wrote:
Rob wrote:
That's fine from the perspective of learning C++/CLI, but I'm trying to use
VS 2005 Beta 2 to write code and I would've thought that correct assignment
operator syntax would've been put into the compiler kind of early on.

I think this should be avoided for anything else than just getting a feeling of the
upcoming C++/CLI.

Nov 17 '05 #12
Rob wrote:
Well that's too bad. The Microsoft people I've spoken with claimed that I
could be pretty confident in using it to write code 1) that works and 2) that
wouldn't need to be rewritten when this thing finally ships.

I do not think any GUI code of Beta 2 will compile in the final product out of the box.
For a start, consider the Dispose() definition inside a Form that is produced by the
Designer. In C++/CLI there is no Dispose() definition, the constructor is used for this.

--
Ioannis Vranos

http://www23.brinkster.com/noicys
Nov 17 '05 #13
Ioannis Vranos wrote:
I do not think any GUI code of Beta 2 will compile in the final product
out of the box. For a start, consider the Dispose() definition inside a
Form that is produced by the Designer. In C++/CLI there is no Dispose()
definition, the constructor is used for this.


Beta 1 didn't handle Dispose correctly and the GUI designer generated
the wrong code. In fact, Beta 1 couldn't compile even a trivial GUI
application, because the designer generated the wrong C++/CLI code. It
didn't use the delete operator, which it should have done. Fortunately
this is fixed in Beta 2, and it's absoltely correct now, as far as I can
tell (I'm not on the C++/CLI standard team, so don't take my words for
granted, and the standard is not finalized yet, so you can't say
anything for sure).

Note that there are two Dispose functions, Dispose(void) and
Dispose(bool). It's true that you can not have a Dispose(void) function
in C++/CLI, and you must use the destructor instead. However, if I'm not
mistaken, you can still have a Dispose(bool) function, which is different.

Dispose(void) is what we know as the destructor, and it is supposed to
be called by the user of every class inherited from IDisposable. In
C++/CLI, it means the delete operator, in other .NET languages
(including MC++ and C#) its the Dispose() call:

object = new MyObject(); or object = gcnew MyObject;
[...] [...]
object.Dispose(); delete object;

If you happen to forget about calling Dispose, or there is an exception
before you have a chance to do so, then the garbage collector
automatically calls the finalizer. The finalizer is slightly different
than Dipose(void), because Dispose(void) is supposed to close everything
that needs to be closed, while the finalizer must only deallocate
unmanaged members. For a more accurate description, consult other
sources (books, msdn). I'm not going to describe the exact differences
here, as some experts have already done a very good job with that elsewhere.

There is, however, a *major* difference between the finalizer and
Dispose(void). On the other hand, in many cases the two things are the
same, or at least very similar. Therefore it makes sense to introduce
another function, which does the cleanup, and is called from both the
finalizer and Dispose(void). This way you don't have to duplicate your
code. So instead of writing your deallocation code twice, you write it
once and put it in a function called Dispose(bool). It's unfortunate
that it has the same name, and I find it confusing too, but this is how
Microsoft did it. This common Dispose has a different signature, it has
a "bool disposing" argument, determines whether Dispose(bool) was called
from Dispose(void) (disposing = true) or from the finalizer (disposing =
false). And this Dispose(bool) is still a valid function in C++/CLI, if
I'm not mistaken.

Tom
Nov 17 '05 #14
Tamas Demjen wrote:
Note that there are two Dispose functions, Dispose(void) and
Dispose(bool). It's true that you can not have a Dispose(void) function
in C++/CLI, and you must use the destructor instead. However, if I'm not
mistaken, you can still have a Dispose(bool) function, which is different.

Dispose(void) is what we know as the destructor, and it is supposed to
be called by the user of every class inherited from IDisposable. In
C++/CLI, it means the delete operator, in other .NET languages
(including MC++ and C#) its the Dispose() call:

object = new MyObject(); or object = gcnew MyObject;
[...] [...]
object.Dispose(); delete object;

If you happen to forget about calling Dispose, or there is an exception
before you have a chance to do so, then the garbage collector
automatically calls the finalizer. The finalizer is slightly different
than Dipose(void), because Dispose(void) is supposed to close everything
that needs to be closed, while the finalizer must only deallocate
unmanaged members.

I just checked MSDN and found this:

http://msdn2.microsoft.com/library/f...us,vs.80).aspx
It seems you are right. However I have got a head ache. :-)
In C++/CLI we do have both destructors ~SomeClass() and finalizers !SomeClass(). The way I
view it is that we can simply do:
class SomeClass
{
bool isCleaned;

// ...

public:

// ...

~SomeClass()
{
// Clean up

isCleaned= true;
}

!SomeClass()
{
if(!isCleaned)
// Clean up (unmanaged resources only)
}
};

Where does Dispose(bool) come into picture when we have both destructors and finalizers?

For a more accurate description, consult other
sources (books, msdn). I'm not going to describe the exact differences
here, as some experts have already done a very good job with that
elsewhere.

There is, however, a *major* difference between the finalizer and
Dispose(void). On the other hand, in many cases the two things are the
same, or at least very similar. Therefore it makes sense to introduce
another function, which does the cleanup, and is called from both the
finalizer and Dispose(void). This way you don't have to duplicate your
code. So instead of writing your deallocation code twice, you write it
once and put it in a function called Dispose(bool). It's unfortunate
that it has the same name, and I find it confusing too, but this is how
Microsoft did it. This common Dispose has a different signature, it has
a "bool disposing" argument, determines whether Dispose(bool) was called
from Dispose(void) (disposing = true) or from the finalizer (disposing =
false). And this Dispose(bool) is still a valid function in C++/CLI, if
I'm not mistaken.

OK, but I suppose this Dispose(bool) is not mandatory and does not affect the use of
classes from other languages. As far as I can understand, if someone wants a common
unmanaged resources clean, he can simply do:
class SomeClass
{
bool isCleaned;

// ...

void CleanUnmanagedItems()
{
// ...
}
public:

// ...

~SomeClass()
{
// Possible clean up of managed resources
// ...

CleanUnmanagedItems();

isCleaned= true;
}

!SomeClass()
{
if(!isCleaned)
CleanUnmanagedItems();
}
};
Nov 17 '05 #15
Ioannis Vranos wrote:
In C++/CLI we do have both destructors ~SomeClass() and finalizers
!SomeClass(). The way I view it is that we can simply do:
class SomeClass
{
bool isCleaned;

// ...

public:

// ...

~SomeClass()
{
// Clean up

isCleaned= true;
}

!SomeClass()
{
if(!isCleaned)
// Clean up (unmanaged resources only)
}
};

Where does Dispose(bool) come into picture when we have both destructors
and finalizers?
It comes in this way:

ref class SomeClass
{
public:
~SomeClass() { Dispose(true); }
!SomeClass() { Dispose(false); }
private:
void Dispose(bool disposing)
{
if(disposing) { DeleteManagedResources(); }
DeleteUnmanagedResources();
}
};

Note that the finalizer is only called when the destructor was not
called. The destructor (I think) automatically disables the finalizer.
So either the ~ or the ! is called, but not both.
OK, but I suppose this Dispose(bool) is not mandatory and does not
affect the use of classes from other languages.
Not in your own classes, as far as I know. I'm really not sure, but I
think the Dispose(bool) function is already there in WinForms classes,
so why not use them? You don't have to, of course.

I simply reacted your email in which you claimed that it was illegal
code and wouldn't compile in the final version. I believe it would,
that's all.
class SomeClass
{
bool isCleaned;

// ...

void CleanUnmanagedItems()
{
// ...
}
public:

// ...

~SomeClass()
{
// Possible clean up of managed resources
// ...

CleanUnmanagedItems();

isCleaned= true;
}

!SomeClass()
{
if(!isCleaned)
CleanUnmanagedItems();
}
};


Now this is something that would work equally well, although I don't
think isCleaned is necessary. Again, the finalizer is only called if and
only if the destructor was not called.

Also, the difference between the finalizer and the destructor is not
that the finalizer clears unmanaged resources only. In many cases that's
the situation, but not always. It's more precise to say that the
finalizer should not call any managed destructor or Dispose, because the
garbage collector calls their finalizer automatically.

There's a main difference between deterministic destruction and GC
finalization. When you call the destructor / Dispose(), you are supposed
to delete / Dispose() disposable managed member owned by the class.
However, when the GC calls the finalizer, it does so for every class
independently. If your finalizer calls member object's finalizers, those
member finalizers will be double called, which is not safe. That's the
main difference between the two.

So

class Unmanaged { [...] }

ref class Inner
{
public:
~Inner() { [...] }
!Inner() { [...] }
};

ref class Outer
{
Inner^ inner;
Unmanaged* u;
public:
~Outer() { delete inner; delete u; }
!Outer() { delete u; }
};

Outer^ outer;

When you call delete outer, it's supposed to delete its managed and
unmanaged members. When you forget about deleting outer, the finalizer
will be called for outer and inner independently, therefore Outer's
finalizer shouldn't delete inner.

I'm not sure where in the object hierarchy Dispose(bool) is introduced.
It's also interesting that every class has a finalizer, but only
IDisposable classes have a destructor. The GC knows about the finalizer,
but doesn't know anything about the destructor / Dispose.

Please correct me if I'm wrong.

Tom
Nov 17 '05 #16
Tamas Demjen wrote:
__gc class SomeClass
{
bool isCleaned;

// ...

void CleanUnmanagedItems()
{
// ...
}
public:

// ...

~SomeClass()
{
// Possible clean up of managed resources
// ...

CleanUnmanagedItems();

isCleaned= true;
}

!SomeClass()
{
if(!isCleaned)
CleanUnmanagedItems();
}
};

Now this is something that would work equally well, although I don't
think isCleaned is necessary. Again, the finalizer is only called if and
only if the destructor was not called.

We are getting in a mess here, however in managed extensions, finalizer is called even if
Dispose() has been called, and we have to determine ourselves if previous clean up has
been done previously via an explicit call to Dispose().
Things change in *C++/CLI* only, with GC::SuppressFinalize() being *implicitly* called in
a destructor, and inheritance from IDisposable being done implicitly when we define a
destructor.
When you call delete outer, it's supposed to delete its managed and
unmanaged members. When you forget about deleting outer, the finalizer
will be called for outer and inner independently, therefore Outer's
finalizer shouldn't delete inner.

I'm not sure where in the object hierarchy Dispose(bool) is introduced.
It's also interesting that every class has a finalizer, but only
IDisposable classes have a destructor. The GC knows about the finalizer,
but doesn't know anything about the destructor / Dispose.
Dispose(bool) is a standardised (recommended) way to define one clean up method for both
situations (instead of repeating code inside destructor and finalizer, or using some other
arbitrary approach).
Please correct me if I'm wrong.


You are explaining things well. :-)
I knew all the things you mentioned but I had forgotten Dispose(bool) existence.
I remember now that I had read about it in my first .NET 1.0 book (a book of MS Press) but
having never used Dispose() explicitly all this time, had made me forget all these details.
Something else interesting now. In C++/CLI, apart from missing the managed extensions
pinning ability of whole managed objects, as far as I know managed extensions also
currently provide the possibility of defining a finalizer as a destructor and invoke
deterministic finalization on managed objects having such a destructor/finalizer.

From the same .NET 1.0 book, I remember that enabling deterministic finalisation on any
managed class, just involves defining a destructor. Check this example:
#using <mscorlib.dll>

__gc class ManagedClass
{
public:
~ManagedClass() {}
};

int main()
{
using namespace System;

ManagedClass *pmc= __gc new ManagedClass;

//Deterministic finalisation
delete pmc;
}
So as far as I can understand (please anyone correct if I am wrong), with managed
extensions, in our managed classes we do not need to even define any Dispose(), but we can
finalise (and not just clean up) explicitly! Unless of course, we want our code to be
usable from other .NET languages.
Nov 17 '05 #17
Some corrections:
Ioannis Vranos wrote:
ref class SomeClass
{
bool isCleaned;

// ...

void CleanUnmanagedItems()
{
// ...
}
public:

// ...

~SomeClass()
{
// Possible clean up of managed resources
// ...

CleanUnmanagedItems();

isCleaned= true;
}

!SomeClass()
{
if(!isCleaned)
CleanUnmanagedItems();
}
};


Now this is something that would work equally well, although I don't
think isCleaned is necessary. Again, the finalizer is only called if
and only if the destructor was not called.
[ Comment removed because I misunderstood/miscorrected the above code sample of mine]
When you call delete outer, it's supposed to delete its managed and
unmanaged members. When you forget about deleting outer, the finalizer
will be called for outer and inner independently, therefore Outer's
finalizer shouldn't delete inner.

I'm not sure where in the object hierarchy Dispose(bool) is
introduced. It's also interesting that every class has a finalizer,
but only IDisposable classes have a destructor. The GC knows about the
finalizer, but doesn't know anything about the destructor / Dispose.



Dispose(bool) is a standardised (recommended) way to define one clean up
method for both situations (instead of repeating code inside destructor
and finalizer, or using some other arbitrary approach).
Please correct me if I'm wrong.



You are explaining things well. :-)
I knew all the things you mentioned but I had forgotten Dispose(bool)
existence.
I remember now that I had read about it in my first .NET 1.0 book (a
book of MS Press) but having never used Dispose() explicitly all this
time, had made me forget all these details.
Something else interesting now. In C++/CLI, apart from missing the
managed extensions pinning ability of whole managed objects, as far as I
know managed extensions also currently provide the possibility of
defining a finalizer as a destructor and invoke deterministic
finalization on managed objects having such a destructor/finalizer.

From the same .NET 1.0 book, I remember that enabling deterministic
finalisation on any managed class, just involves defining a destructor.
Check this example:
#using <mscorlib.dll>

__gc class ManagedClass
{
public:
~ManagedClass() {}
};

int main()
{
using namespace System;

ManagedClass *pmc= __gc new ManagedClass;

//Deterministic finalisation
delete pmc;
}
So as far as I can understand (please anyone correct if I am wrong),
with managed extensions, in our managed classes we do not need to even
define any Dispose(), but we can finalise (and not just clean up)
explicitly! Unless of course, we want our code to be usable from other
.NET languages.

Nov 17 '05 #18
Ioannis Vranos wrote:
We are getting in a mess here, however in managed extensions, finalizer
is called even if Dispose() has been called, and we have to determine
ourselves if previous clean up has been done previously via an explicit
call to Dispose().
Managed extensions doesn't have the concept of destructors. Dispose
doesn't automatically call SuppressFinalize().
Things change in *C++/CLI* only, with GC::SuppressFinalize() being
*implicitly* called in a destructor, and inheritance from IDisposable
being done implicitly when we define a destructor.
Exactly, that's correct. I thought the same. So this is a major
difference between Dispose and C++/CLI d'tors. Thanks for mentioning this.

From the same .NET 1.0 book, I remember that enabling deterministic
finalisation on any managed class, just involves defining a destructor.


In C++/CLI it's one more step ahead, because you create the object using
stack syntax, which adds exception safety:

ManagedClass mc;
mc.xxx();
// no need to delete

Note that the object is still created on the managed heap, not on the stack.

Tom
Nov 17 '05 #19
Tamas Demjen wrote:
Things change in *C++/CLI* only, with GC::SuppressFinalize() being
*implicitly* called in a destructor, and inheritance from IDisposable
being done implicitly when we define a destructor.

Exactly, that's correct. I thought the same. So this is a major
difference between Dispose and C++/CLI d'tors. Thanks for mentioning this.

Well, yes it is a difference in the sense that it is done implicitly along with chaining
calls to Dispose. However with C++/CLI, the destructor is the Dispose() (when other
languages call Dispose() in our objects, the "destructors" are called with all these
implicit features).

From the same .NET 1.0 book, I remember that enabling deterministic
finalisation on any managed class, just involves defining a destructor.

In C++/CLI it's one more step ahead, because you create the object using
stack syntax, which adds exception safety:

ManagedClass mc;
mc.xxx();
// no need to delete

Note that the object is still created on the managed heap, not on the
stack.

Yes. However this is about deterministic destruction (clean up/Dispose), while in managed
extensions it is about deterministic finalization! (if I am not mistaken).

Nov 17 '05 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

42
by: Edward Diener | last post by:
Coming from the C++ world I can not understand the reason why copy constructors are not used in the .NET framework. A copy constructor creates an object from a copy of another object of the same...
15
by: A | last post by:
Hi, A default copy constructor is created for you when you don't specify one yourself. In such case, the default copy constructor will simply do a bitwise copy for primitives (including...
3
by: Aire | last post by:
Will defining a copy constructor also make the default constructor not available anymore, until a default constructor is explicitly provided? Thanks!
8
by: trying_to_learn | last post by:
Why do we need to explicitly call the copy constructor and the operator = , for base class and member objects in composition? ....book says "You must explicitly call the GameBoard copy-constructor...
45
by: Ben Blank | last post by:
I'm writing a family of classes which all inherit most of their methods and code (including constructors) from a single base class. When attempting to instance one of the derived classes using...
4
by: Francisco Amaro | last post by:
Hi all, Have question about inheriting a class that has parameters in the constructor such as : Public MustInherit Class MyParentClass Public mystring As String Public Sub New(ByVal...
1
by: Carl Fenley | last post by:
I've been programming exclusively in C# for the last few years but am now working on a project where I am required to write all code in VB.NET. I'm trying to create a class with multiple...
8
by: shuisheng | last post by:
Dear All, I am wondering how the default copy constructor of a derived class looks like. Does it look like class B : public A { B(const B& right) : A(right) {}
2
by: Jeroen | last post by:
Hi all, I wrote a little bit of code to see the behaviour of (copy) constructors of base and derived classes. But I have a question about it. Let me explain by the following...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.