Topic: ctor cannot be explicitly called?


Author: kanze@us-es.sel.de (James Kanze)
Date: 29 Apr 93 18:23:03
Raw View
In article <C5wr85.154@cbnewse.cb.att.com> grumpy@cbnewse.cb.att.com
(Paul J Lucas) writes:

|> From article <1993Apr22.182921.18139@kronos.arc.nasa.gov>, by abp@kronos.arc.nasa.gov (Andy Philips):

|>  ...

|>  Yet another misposted question.  This one was about calling a
|>  ctor directly from within a *friend* op=.

|>  You should post "How do I..." questions to comp.lang.c++; the std
|>  is for *standard*...get it?  About the language standard?

|>  Anyway, op=() *must* be a member and it has no business constructing
|>  a new object...you're s'posed to be replacing the current object's
|>  contents.

You should have quoted the entire article.  The original poster did
not ask how to call the constructor explicitly (or at least, that was
not his only question).  He asked why it was banned.  Which IMHO is a
standards question.  (I too am curious, even if I know how to call it
indirectly.)
--
James Kanze                             email: kanze@us-es.sel.de
GABI Software, Sarl., 8 rue du Faisan, F-67000 Strasbourg, France
Conseils en informatique industrielle --
                   -- Beratung in industrieller Datenverarbeitung




Author: abp@kronos.arc.nasa.gov (Andy Philips)
Date: Thu, 22 Apr 1993 18:29:21 GMT
Raw View
I can call the dtor for a class explictly, how come I cannot
explicitly call the ctor for a class?

Obligitory class def'n:

class A {
// stuff of the class...

 public:
  A();
  A(const A &);
  ~A();
  friend A & operator=(const A & rhs);
};

I would like to be able to make the following def'n for op=:

A & operator=(const A & rhs)
{
  if (this != &rhs) {
    this->A::~A();
    this->A::A(rhs);
  }
  return *this;
}


But, I can't because I'm not allowed to call the copy constructor and,
therefore, cannot reuse its code.  I assume there must be a good
reason for this, but being a novice, I have not heard the arguments.
Anyone out there care to enlighten me?

--
==============================================================
= Andy Philips             = '76 BMW R90/6 = SMC #3 DoD #223 =
= abp@ptolemy.arc.nasa.gov =   '73 CL175   =   AMA #580929   =
==============================================================




Author: marc@offline.be (Marc Duponcheel)
Date: 22 Apr 93 23:57:30 PST
Raw View
In article <1993Apr22.182921.18139@kronos.arc.nasa.gov> abp@kronos.arc.nasa.gov (Andy Philips) writes:

> A & operator=(const A & rhs)
> {
>   if (this != &rhs) {
>     this->A::~A();
>     this->A::A(rhs);
>   }
>   return *this;
> }

I usually write :

#include <new.h>

A & operator=(const A & rhs)
{
  if (this != &rhs) {
    this->A::~A();
    new(this) A(rhs);
  }
  return *this;
}

-- marc

##########################################################################
  preferred address = marc@offline.be
  e-mail marc@offline.be marc@offline.UUCP offline!marc ub4b!offline!marc
  fido   2:292/603.26 Marc.Duponcheel@p26.f603.n292.z2.FidoNet.Org
  bix    mduponcheel mduponcheel@BIX.com
##########################################################################




Author: robert@alkymi.unit.no (Robert Schmidt)
Date: Thu, 22 Apr 93 22:28:42 GMT
Raw View
In article <1993Apr22.182921.18139@kronos.arc.nasa.gov>, abp@kronos.arc.nasa.gov (Andy Philips) writes:
>
> I would like to be able to make the following def'n for op=:
>
> A & operator=(const A & rhs)
> {
>   if (this != &rhs) {
>     this->A::~A();

By continuing after the above line, you assume that *this exists,
which it doesn't since you just destroyed it.  this is now pointing
to garbage.  You can't call a member function of an object which
doesn't exist, even if it makes member accesses or not, and
a constructor *is* per definition a member function.

Why not do it as simple as providing two memeber functions,
one which deletes the member objects, and another which allocates
them?  For me that's the natural and OO way.  The destructor and
constructor of A would then call these functions also.

Calling the destructor explicitly is rarely used.  I haven't yet
needed to do it, and when you face a situation which seems to need
this, I would recommend you to take a different approach.  I am
not even sure I understand why it was allowed anyway, as it calls
for confusion like the one shown in your post.

To guide you: have a look at this example.  Notice the simple assignment
operator, which can even bear to be inline.  Also, the assignment
operator is traditionally a member function, not a global one
like the one you use.  If you don't supply an operator=(), the
compiler will make a default one which does a member-wise copy,
and this default assignment operator is a member function.

class A
  {
  int size;
  char *store;
  void alloc(const A &a)
    { size=a.size; store=new char[size]; memcpy(store,a.store,size); }
  void free()
    { if (store) delete store; size=0; }
public:
  A()
    { size=store=0; }
  A(const A &a)
    { alloc(a); }
  ~A()
    { free(); }
  A &operator =(const A &a)
    { free(); alloc(a); return *this; }
  };

A final note.  To call the standard library alloc() and free(), you'd
of course use ::alloc() and ::free() inside the A class.

A::alloc() and A::free() ought to be private, like above, to
restrict access.

(I think this is the last time I'll reply to this kind of question.
Is it in the faq, by the way?)

--
Robert Schmidt - robert@alkymi.unit.no - Buuud@IRC
Ztiff Zox Softwear: fast/tiny utilities, games/graphics programming on
                    the DOS platform (C/C++ & asm).  Suggestions welcome!

This is a .sig coke can!  Pour me into your .sig, and join in!




Author: grumpy@cbnewse.cb.att.com (Paul J Lucas)
Date: Thu, 22 Apr 1993 23:14:28 GMT
Raw View


Author: jimad@microsoft.com (Jim Adcock)
Date: 23 Apr 93 18:21:11 GMT
Raw View
In article <1993Apr22.182921.18139@kronos.arc.nasa.gov> abp@kronos.arc.nasa.gov (Andy Philips) writes:
|I would like to be able to make the following def'n for op=:
|
|A & operator=(const A & rhs)
|{
|  if (this != &rhs) {
|    this->A::~A();
|    this->A::A(rhs);
|  }
|  return *this;
|}
|
|But, I can't because I'm not allowed to call the copy constructor and,
|therefore, cannot reuse its code.  I assume there must be a good
|reason for this, but being a novice, I have not heard the arguments.
|Anyone out there care to enlighten me?

Copy constructors may be performing actions in addition to the actions
you explicitly specify.  They may have to set up vtable pointers, vbase
pointers, optionally allocating memory for the object if it is to be
constructed on the heap, etc.  If you could call constructors, you could
be getting these additional hidden side effects.  The solution is
typically to implement an additional helper function to perform the
the common actions, and then call that helper function from both the
constructor and from the assignment operator.  Alternately, you may be
able to write you operator= so that it can be called inside the constructor --
although personally I would consider that bad style -- a constructor is
a constructor, and an assignment operator is an assignment operator, and
the two should not be confused.  Better, if they have something in common, then
factor that common part out, and then call that common part explicitly.





Author: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Date: Sat, 24 Apr 1993 08:44:58 GMT
Raw View
abp@kronos.arc.nasa.gov (Andy Philips) writes:

>I can call the dtor for a class explictly, how come I cannot
>explicitly call the ctor for a class?

You can. You need to use the placement operator new.

>Obligitory class def'n:
>
>class A {
>// stuff of the class...
>
> public:
>  A();
>  A(const A &);
>  ~A();
>  friend A & operator=(const A & rhs);
>};
>
>I would like to be able to make the following def'n for op=:
>
>A & operator=(const A & rhs)
>{
>  if (this != &rhs) {
>    this->A::~A();
>    this->A::A(rhs);
The above line should be replaced by
     new(this) A(rhs);
You might also need to #include <new.h>.
>  }
>  return *this;
>}

--
Fergus Henderson             fjh@munta.cs.mu.OZ.AU
This .signature virus is a self-referential statement that is true - but
you will only be able to consistently believe it if you copy it to your own
.signature file!