comp.lang.ada
 help / color / mirror / Atom feed
* Re: on OO differnces between Ada95 and C++
  1996-02-20  0:00 Nasser Abbasi
  1996-02-20  0:00 ` Robert I. Eachus
  1996-02-20  0:00 ` Norman H. Cohen
@ 1996-02-20  0:00 ` Jerome Desquilbet
  1996-02-21  0:00   ` Robert Dewar
  1996-02-22  0:00   ` Pete Becker
  1996-02-21  0:00 ` Jon S Anthony
                   ` (2 subsequent siblings)
  5 siblings, 2 replies; 25+ messages in thread
From: Jerome Desquilbet @ 1996-02-20  0:00 UTC (permalink / raw)
  To: Nasser Abbasi

Nasser,

You have pointed out one of the main differences between Ada and C
compilation models (and as far as the compilation model is concerned,
Ada 95 is not different from Ada 83, and C++ is not different from C).


- The C/C++ compilation paradigm is _independent_ compilation.

- The Ada 83/95 compilation paradigm is _separate_ compilation.


It has nothing to do with the OO features of the two languages.


The comparison between these two compilation models would take some
place, but here a list of some comments about the C/C++ compilation
model:

- .C files may be compiled in any order

- .h files are not compiled

- there is no way to avoid use of the preprocessor (at least for
#include)

- there is no way to oblige the programmer to write all the #include
directives: he may take advantage of some "hidden" includes (nested at
more than one level)

- the really compiled file (the compilation unit) is the result of the
preprocessing phase

- conventions like

  #ifndef X_H_
  #define X_H_
  ...
  #endif

  in headers to prevent multi-inclusion are only conventions, they are
not part of the language

- you may have several different definitions for the same class in the
same program, as long as they are never compiled together in the same
compilation unit; example:

#define private public // *** BERK! ***
#include "...h"        // second definition for the same class
#undef private

  Jerome.




^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
  1996-02-20  0:00 Nasser Abbasi
  1996-02-20  0:00 ` Robert I. Eachus
@ 1996-02-20  0:00 ` Norman H. Cohen
  1996-02-21  0:00   ` Mark A Biggar
  1996-02-27  0:00   ` Adam Morris
  1996-02-20  0:00 ` Jerome Desquilbet
                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 25+ messages in thread
From: Norman H. Cohen @ 1996-02-20  0:00 UTC (permalink / raw)


In article <4gbq7q$g08@qualcomm.com>, nabbasi@qualcomm.com (Nasser Abbasi)
observes that in C and C++ one specifies an interface in a .h (or .H)
file and imports the interface with a #include directive, while in Ada
one specifies an interface with a program-unit declaration (typically a
package declaration) and imports it with a with clause.  In C and C++
importing is transitive--if B #includes A and C #includes B, then C has
effectively #included--while in Ada it is not--if B has a with clause for
A and C has a with clause for B, then A is not visible in C unless C has
its own explicit with clause for A.

I prefer the Ada model for two reasons: 

1.  The Ada model provides a more precise description of which library
    units are visible where.  A library unit is visible only in
    compilation units naming it in a with clause.  Some Ada programmers
    use subunits to make this information even more precise.  For
    example, if the only place in a large package body where Ada.Text_IO
    is used is in one particular procedure body, that procedure body may
    be broken off into a subunit and the with clause for Ada.Text_IO
    placed on the subunit rather than the package body, to make clear to
    readers that Ada.Text_IO is only used in that one procedure.

2.  In a compilation unit U that refers to an imported entity X, the Ada
    model makes it easier to find the unit exporting X.  It must be a
    unit named in a with clause on U, on the corresponding declaration if
    U is a body, or a parent unit.

When the programmers deem it appropriate, it is possible for one package
to reexport entities declared in another package using renaming, subtype,
and number declarations: 

   package A is
      type T is ...;
      procedure P(X: in out T);
      Y: constant T := ...;
      ...
   end A;

   with A;
   package B is
      subtype T is A.T;
      procedure P(X: in out T) renames A.P;
      Y: constant T := A.C;
      ...
   end B;

However, reexport is not forced on the programmer as in the case of a .h
file that #includes another .h file.  In the example above, if a
compilation unit C has a with clause for B and refers to T, P, or Y, the
reader for C can refer to the declaration of B to find declarations for
T, P, and Y.

In OOP, it is often desirable for entities declared along with a parent
type P to be reexported along with any type D derived from P.  This can
be achieved automatically by deriving from P in a child of the package in
which D is declared: 

   package Parent is
      type Auxiliary_Type is ...;
      type P is tagged ...;
      procedure Op (X: in out P; Y: in Auxiliary_Type);
      ...
   end Parent;

   package Parent.Child is
      type D is new P with ...;
      procedure Op (X: in out D; Y: in Auxiliary_Type);
      ...
   end Parent.Child;

A compilation unit that mentions Parent.Child in a with clause is, in
effect, really importing a version of Parent with Parent.Child nested
inside of it, so the declaration of Auxiliary_Type comes along.

--
Norman H. Cohen    ncohen@watson.ibm.com




^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
  1996-02-20  0:00 Nasser Abbasi
@ 1996-02-20  0:00 ` Robert I. Eachus
  1996-02-20  0:00 ` Norman H. Cohen
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 25+ messages in thread
From: Robert I. Eachus @ 1996-02-20  0:00 UTC (permalink / raw)


In article <4gbq7q$g08@qualcomm.com> nabbasi@qualcomm.com (Nasser Abbasi) writes:

  > I have been playing around with the OO features in Ada95 and
  > comparing it with C++. I noticed this little difference, and I'd
  > like to see what you think of it...

  > In C++, the client to the saving_account class can also use the
  > Money_Type type (even though that is defined in the base class
  > Account) without having to include base class "account.h", this is
  > because Money_Type has become a public part of the Saving_Account
  > class when Saving_Account inherited Saving class.

    Not quite true. The visibility is because the copy semantics
associated with #include are transitive.  Anyone who includes
saving_account also copies account, and in fact the "standard" C
idiom of defining a global and testing it around #includes is to avoid
including multiple copies.

  > In Ada95, the client of Saving_Account has no viability to Money_Type
  > type definition even though they with'ed Saving_account package, since
  > Money_Type is not a "inherited" by the Saving_Account package
  > from the Account package.

    Again it is a little more complex than that.  In Ada 95 the type is
in scope throughout all of the semantic dependents, but the name of
the type or of its operations is visible in a subset of that range.
In any case there are several different ways of making visible (or
directly visible) the name and operations of Money_Type.

  > This means that in Ada95, If one wants to access things like type
  > definitions that are not tagged, but used in defining components
  > inside the tagged record, one must "with" the client package and
  > also packages that the client package with'ed just to be able to
  > have viability to those type definitions.

    No, another solution is to re-export them from Saving_Account.
That is seldom the right solution in Ada, and is probably not right
here. 

  > In this case, It seems the C++ way of having everything inside the
  > public base class becoming visible to clients of the derived class
  > that inherits the base class is more economical?.

  > ...Any better way?

     Yes, 1) restructure your program to use child packages:

   ----------------- accounting.ads

   package Accounting is

     type Money_Type is delta 0.01 digits 9; -- just my example ;-)
     type Account_Id is private;

   private

     type Account_Id is new Integer;

   end Accounting;

   ------------------ account.ads ---------------------------

   package Accounting.Account is

     type Account_Type is tagged private;
  
     -- operations on type Account_Type defined here including

     procedure Set_Balance(A: Account, M: Accounting.Money_Type);

   private

     function New_Account_ID return Account_ID;

     type Account_Type is tagged
      record
	Balance    : Money_Type := 0.0;
	Id         : Account_Id := New_Account_ID;
      end record;

   end Account;

   ----------------- saving_account.ads ----------------

   with Accounting.Account;
   package Saving_Account is

    type Saving_Account_Type is new Account.Account_Type with private;

    -- new operations on savings accounts defined here including

   private

    type Saving_Account_Type is new Account.Account_Type with
      record
	Interest : Account.Money_Type;
      end record;

   end Saving_Account;

   --------------- main.adb ---------------------------

   with Accounting.Saving_Account;
   -- with of Accounting is implicit, with of Accounting.Acount unneeded.
   with Ada.Text_IO; use Ada.Text_IO;

   procedure main is       
     package Money_IO is new Ada.Text_IO.Decimal_IO(Accounting.Money_Type);
     The_Saving_Account : Saving_Account.Saving_Account_Type;
     The_Balance : Accounting.Money_Type; 
   begin
       Money_IO.Get(The_Balance);
       Set_Balance(The_Saving_Account, The_Balance);
   end Main;

   I added the use of private parts to emphasize the way this works.
The operations declared explicitly or implicitly within the private
part of Accounting are visible within the children of Accounting as
well.  So I could, if I wanted, hide the full declaration of
Money_Type, and the instantiation of Money_IO within the private part
of Accounting, and explicitly export operations which do IO from
Accounting.Account.  Of course this would implicitly define the same
operations for Saving_Account and/or I could add additional IO
operations.

    All in all a bit heavy for such a small example.  But in larger
programs, you find yourself pushing for information hiding wherever
possible.

--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




^ permalink raw reply	[flat|nested] 25+ messages in thread

* on OO differnces between Ada95 and C++
@ 1996-02-20  0:00 Nasser Abbasi
  1996-02-20  0:00 ` Robert I. Eachus
                   ` (5 more replies)
  0 siblings, 6 replies; 25+ messages in thread
From: Nasser Abbasi @ 1996-02-20  0:00 UTC (permalink / raw)




Hello,

I have a simple comment, but probably a long way of 
showing it :)

I have been playing around with the OO features in Ada95 and
comparing it with C++. I noticed this little difference, and I'd
like to see what you think of it.

Lets assume we have a base class called Account, and a class called
Saving_Account that uses Account as base. 

Lets also assume that we need to define a Money Type, defined in
the base class Account.     

In Ada95 this type is defined in the package Account.ads that also
includes the definition of the tagged record type Account (along with
operations that act on Account type).

In C++, this Money Type is typedef'ed inside the public part of the
class Account, and it becomes part of the public interface of the
base class.

so far so good.

Now, In Ada95, a client that wishes to use Saving_Account type (and
any operations on it) will "with" the Saving_Account Package.

Also, in C++, a client who wishes to use Saving_Account class will
include "saving_account.h"

There is some differences though.

In C++, the client to the saving_account class can also use the
Money_Type type (even though that is defined in
the base class Account) without having to include base class
"account.h", this is because Money_Type has become a public part of the
Saving_Account class when Saving_Account inherited Saving class.

In Ada95, the client of Saving_Account has no viability to Money_Type
type definition even though they with'ed Saving_account package, since
Money_Type is not a "inherited" by the Saving_Account package
from the Account package. This means that in Ada95, If one wants to
access things like type definitions that are not tagged, but 
used in defining components inside the tagged record, one must
"with" the client package and also packages that the client package
with'ed just to be able to have viability to those type definitions.

I understand the reason why in Ada95 one must do this,
a client "with"ing a package has only viability to the public part
of that package and not to any packages that that package may have
"with"ed. 

In this case, It seems the C++ way of having everything inside
the public base class becoming visible to clients of the derived class
that inherits the base class is more economical?. 
(everything means, data members, methods members and things like 
enum, typedefs, structs. etc..) In Ada95 only certain type 
(the tagged record type) and methods on this type can be seen 
by clients of the extended type.


One way to go around having in Ada95 to "with" both Account and
Saving_Account packages, is that in the Saving_Account package 
to introduce new type Money_Type made of the Account.Money_Type,
this way clients of Saving_Account can see Money_Type type by just
"with"ing Saving_Account package and not have to "with" account
package also just to use the Money_Type. 

But this means that type definitions has to be manually "propagated" from
one package to another so that clients of the last package in the chain
have only to "with" that last package. Any better way?

Just to put all this in example, (In case the above got to winded :) , 
I have an example to show I mean. I show the Ada code, and below it the 
C++ code. You see that in Ada, the main.adb had to "with" both Account 
and Saving_account, while in C++, the main had to only include 
"saving_account.h" .

thanks,
Nasser
 Learning_Ada95_OO_features...

------------------ account.ads ---------------------------
package Account is
 type Money_Type is new integer range 1..100; -- just as an example
 type Account_Type is tagged
   record
     Balance    : Money_Type;
     Account_Id : Integer; 
   end record;
end Account;

----------------- saving_account.ads ----------------
with Account;
Package Saving_Account is
 type Saving_Account_Type is new Account.Account_Type with
   record
     Interest : Account.Money_Type;
   end record;

   -- here we could also type this:
   --
   -- Type Money_Type is new Account.Money_Type
   --
   -- this way Money_Type can be made visible to clients
   -- of saving account without having to "with" Account package.
   -- we have propogated Money_Type to this package from the
   -- "with"ed package, so that clients to this package can see
   -- this type without having to "with" the Account package
   -- JUST to access Money_Type
   --
end Saving_Account;

--------------- main.adb ---------------------------

with Account;   -- only reason with'ed is to have visibility to
                -- money_type. in C++, the main can see the Money_Type
                -- through Saving_Account, and do not have to include
                -- the base class Account
with Saving_Account;
with ada.text_io; use ada.text_io;

procedure main is       
  package Money_IO is new Ada.Text_IO.Integer_IO(Account.Money_Type);
  The_Saving_Account : Saving_Account.Saving_Account_Type;
  The_Balance : Account.Money_Type; 
  begin
    Money_IO.Get(The_Balance);
    The_Saving_Account.Balance := The_Balance;
end main;

==============================

Now the C++ way:


--------------- account.h -------------------
class Account
{
  public:
  typedef int Money_Type;
  Money_Type Balance;
  int        Account_Id;
};

-------------- saving_account.h -----------------

#include "saving_account.h" 
class Saving_Account : public Account
{
  public:
  Money_Type Interest;
};

--------------- main.cpp -----------------

#include <iostream.h>
#include "saving_account.h"  // Notice: no need to include to base class
                             // Account in account.h
main()
{
Saving_Account             The_Saving_Account;
Saving_Account::Money_Type  The_Balance;  // notice, Money_Type accessed
                                          // through Saving_Account and
                                          // no need to include the
                                          // base class account

 cout << "Balance?";
 cin  >> The_Balance;
 The_Saving_Account.Balance = The_Balance;

return 1;

}







^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
@ 1996-02-21  0:00 Christian Jaensch, FRG
  0 siblings, 0 replies; 25+ messages in thread
From: Christian Jaensch, FRG @ 1996-02-21  0:00 UTC (permalink / raw)


Nasser Abbasi <nabbasi@QUALCOMM.COM> wrote:
> Hello,
>
> I have a simple comment, but probably a long way of
> showing it :)
>
> I have been playing around with the OO features in Ada95 and
> comparing it with C++. I noticed this little difference, and I'd
> like to see what you think of it.
[rest snipped...]

  Below, I slightly modified your example using the parent-child approach.
This gets rid of the aspect that seemed that have bothered you (explicit
with of package Account needed in main) in your approach.
BTW, whenever things are closely related or types are extended as in your
example, I preferably use the hierarchical package approach. It provides
-- if done well -- amongst other benefits a fairly transparent view of the
class hierarchy. Besides, the parent-child approach is needed if you make
all your to be extended types private ;-).

------------------ account.ads ---------------------------
package Account is

 type Money_Type is new integer range 1..100; -- just as an example

 type Account_Type is tagged
   record
     Balance    : Money_Type;
     Account_Id : Integer;
   end record;

end Account;

----------------- account-saving_account.ads ------------
Package Account.Saving_Account is

 type Saving_Account_Type is new Account_Type with
   record
     Interest : Money_Type;
   end record;

   -- ...
end Account.Saving_Account;

--------------- main.adb ---------------------------
with Account.Saving_Account; -- provides implicit with clause of parent
with Ada.Text_IO; use Ada.Text_IO;

procedure Main is

  package Money_IO is new Ada.Text_IO.Integer_IO(Account.Money_Type);

  The_Saving_Account : Account.Saving_Account.Saving_Account_Type;
  The_Balance        : Account.Money_Type;

begin

    Money_IO.Get(The_Balance);
    The_Saving_Account.Balance := The_Balance;

end Main;

I hope this helps,
--
    _/_/_/_/   _/_/_/_/  _/_/_/_/   Christian Jaensch   TEL: +49(0)881-64947
      _/      _/    _/        _/    Narbonner Ring 14   FAX: +49(0)881-637444
     _/      _/_/_/          _/     82362 Weilheim
    _/      _/    _/        _/      FRG
_/_/_/_/   _/_/_/_/    _/_/_/
C  O  N  S  U  L  T  I  N  G        em: chris@ifr.luftfahrt.uni-stuttgart.de
-----------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
  1996-02-20  0:00 ` Norman H. Cohen
@ 1996-02-21  0:00   ` Mark A Biggar
  1996-02-22  0:00     ` Norman H. Cohen
  1996-02-27  0:00   ` Adam Morris
  1 sibling, 1 reply; 25+ messages in thread
From: Mark A Biggar @ 1996-02-21  0:00 UTC (permalink / raw)


In article <4gdidj$10f5@watnews1.watson.ibm.com> ncohen@watson.ibm.com writes:
>   package Parent is
>      type Auxiliary_Type is ...;
>      type P is tagged ...;
>      procedure Op (X: in out P; Y: in Auxiliary_Type);
>      ...
>   end Parent;
>
>   package Parent.Child is
>      type D is new P with ...;
>      procedure Op (X: in out D; Y: in Auxiliary_Type);
>      ...
>   end Parent.Child;
>
>A compilation unit that mentions Parent.Child in a with clause is, in
>effect, really importing a version of Parent with Parent.Child nested
>inside of it, so the declaration of Auxiliary_Type comes along.

Given the above example, is the following code legal, I have been unable to 
determine if it is from the RM95:

with Parent.Child;
package My_Package is

  A: Parent.Child.Auxiliary_Type;  -- or must I say A: Parent.Auxiliary_Type

end My_Package;

If the above is illegal then it presents a problem if I have a library
level renaming of Parent.Child, like so:

package My_Child renames Parent.Child;

with My_Child;
package Foo is

  A: My_Child.Auxiliary_Type; -- LEGAL?

end Foo;

If this type of naming is legal then there is a simple emulation of
Norman's multi-part package proposal using child packages and a library
level rename.

--
Mark Biggar
mab@wdl.loral.com








^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
  1996-02-20  0:00 Nasser Abbasi
                   ` (4 preceding siblings ...)
  1996-02-21  0:00 ` John English
@ 1996-02-21  0:00 ` Darren C Davenport
  5 siblings, 0 replies; 25+ messages in thread
From: Darren C Davenport @ 1996-02-21  0:00 UTC (permalink / raw)


Nasser Abbasi (nabbasi@qualcomm.com) wrote:


: Hello,

: I have a simple comment, but probably a long way of 
: showing it :)

: I have been playing around with the OO features in Ada95 and
: comparing it with C++. I noticed this little difference, and I'd
: like to see what you think of it.

: Lets assume we have a base class called Account, and a class called
: Saving_Account that uses Account as base. 

: Lets also assume that we need to define a Money Type, defined in
: the base class Account.     

: In Ada95 this type is defined in the package Account.ads that also
: includes the definition of the tagged record type Account (along with
: operations that act on Account type).

: In C++, this Money Type is typedef'ed inside the public part of the
: class Account, and it becomes part of the public interface of the
: base class.

: so far so good.

: Now, In Ada95, a client that wishes to use Saving_Account type (and
: any operations on it) will "with" the Saving_Account Package.

: Also, in C++, a client who wishes to use Saving_Account class will
: include "saving_account.h"

: There is some differences though.

: In C++, the client to the saving_account class can also use the
: Money_Type type (even though that is defined in
: the base class Account) without having to include base class
: "account.h", this is because Money_Type has become a public part of the
: Saving_Account class when Saving_Account inherited Saving class.

: In Ada95, the client of Saving_Account has no viability to Money_Type
: type definition even though they with'ed Saving_account package, since
: Money_Type is not a "inherited" by the Saving_Account package
: from the Account package. This means that in Ada95, If one wants to
: access things like type definitions that are not tagged, but 
: used in defining components inside the tagged record, one must
: "with" the client package and also packages that the client package
: with'ed just to be able to have viability to those type definitions.

The other option is to to put Saving_Account_Type into to a child
package of account, say account.savings.  Then when you with account.savings
you get the anything the parent package has that's visible.

Darren





^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
  1996-02-20  0:00 Nasser Abbasi
                   ` (3 preceding siblings ...)
  1996-02-21  0:00 ` Jon S Anthony
@ 1996-02-21  0:00 ` John English
  1996-02-22  0:00   ` Nasser Abbasi
  1996-02-22  0:00   ` Gene Ouye
  1996-02-21  0:00 ` Darren C Davenport
  5 siblings, 2 replies; 25+ messages in thread
From: John English @ 1996-02-21  0:00 UTC (permalink / raw)


Nasser Abbasi (nabbasi@qualcomm.com) wrote:
: Lets also assume that we need to define a Money Type, defined in
: the base class Account.     

: In Ada95 this type is defined in the package Account.ads that also
: includes the definition of the tagged record type Account (along with
: operations that act on Account type).

: Now, In Ada95, a client that wishes to use Saving_Account type (and
: any operations on it) will "with" the Saving_Account Package.

If the spec of Saving_Account has "with Account" at the beginning,
"with Saving_Account" will imply "with Account".  Or use child
packages: make Saving_Account a child of Account (e.g. Account.Saving)
so that it is effectively an extension of Account.

: In C++, the client to the saving_account class can also use the
: Money_Type type (even though that is defined in
: the base class Account) without having to include base class
: "account.h", this is because Money_Type has become a public part of the
: Saving_Account class when Saving_Account inherited Saving class.

You can always put "subtype Money_Type is Account.Money_Type" in
Saving_Account to make it directly usable from Saving_Account...

-- 
----------------------------------------------------------------------------
John English <je@brighton.ac.uk>, Dept. of Computing, University of Brighton
  "Disks are divided into sex and tractors..."
----------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
  1996-02-20  0:00 ` Jerome Desquilbet
@ 1996-02-21  0:00   ` Robert Dewar
  1996-02-22  0:00     ` Jerome Desquilbet
  1996-02-22  0:00   ` Pete Becker
  1 sibling, 1 reply; 25+ messages in thread
From: Robert Dewar @ 1996-02-21  0:00 UTC (permalink / raw)


In Jerome's list, the two entries:

- .C files may be compiled in any order

- .h files are not compiled


As GNAT shows, there is no need to have a specific order of compilation
for Ada files, and GNAT does not require specs to be explicitly copiled
(although it permits it, which is the way I would state the advantage).





^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
  1996-02-20  0:00 Nasser Abbasi
                   ` (2 preceding siblings ...)
  1996-02-20  0:00 ` Jerome Desquilbet
@ 1996-02-21  0:00 ` Jon S Anthony
  1996-02-21  0:00 ` John English
  1996-02-21  0:00 ` Darren C Davenport
  5 siblings, 0 replies; 25+ messages in thread
From: Jon S Anthony @ 1996-02-21  0:00 UTC (permalink / raw)


In article <4gbq7q$g08@qualcomm.com> nabbasi@qualcomm.com (Nasser Abbasi) writes:

Use child packages.  For example,

>  Learning_Ada95_OO_features...
> ...
> Now the C++ way:
> 
> 
> --------------- account.h -------------------
> class Account
> {
>   public:
>   typedef int Money_Type;
>   Money_Type Balance;
>   int        Account_Id;
> };
> 
> -------------- saving_account.h -----------------
> 
> #include "saving_account.h" 
> class Saving_Account : public Account
> {
>   public:
>   Money_Type Interest;
> };
> 
> --------------- main.cpp -----------------
> 
> #include <iostream.h>
> #include "saving_account.h"  // Notice: no need to include to base class
>                              // Account in account.h
> main()
> {
> Saving_Account             The_Saving_Account;
> Saving_Account::Money_Type  The_Balance;  // notice, Money_Type accessed
>                                           // through Saving_Account and
>                                           // no need to include the
>                                           // base class account
> 
>  cout << "Balance?";
>  cin  >> The_Balance;
>  The_Saving_Account.Balance = The_Balance;
> 
> return 1;
> 
> }

Ada version (from your stuff...):

> ------------------ account.ads ---------------------------
> package Account is
>  type Money_Type is new integer range 1..100; -- just as an example
>  type Account_Type is tagged
>    record
>      Balance    : Money_Type;
>      Account_Id : Integer; 
>    end record;
> end Account;

----------------- Account-Savings.ads ----------------

Package Account.Saving_Account is

 -- Note: all the stuff in Account is visible here

 type Saving_Account_Type is new Account.Account_Type with
   record
     Interest : Account.Money_Type;
   end record;

end Saving_Account;

> --------------- main.adb ---------------------------
> 
with Account.Saving_Account;
--
-- Note: visibility of Account comes along with Saving_Account here.

with ada.text_io; use ada.text_io;

procedure main is

  package Money_IO is new Ada.Text_IO.Integer_IO(Account.Money_Type);
  The_Saving_Account : Saving_Account.Saving_Account_Type;
  The_Balance : Account.Money_Type; 
  begin
    Money_IO.Get(The_Balance);
    The_Saving_Account.Balance := The_Balance;
end main;
-- 
Jon Anthony
Organon Motives, Inc.
1 Williston Road, Suite 4
Belmont, MA 02178

617.484.3383
jsa@organon.com





^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
  1996-02-21  0:00   ` Robert Dewar
@ 1996-02-22  0:00     ` Jerome Desquilbet
  1996-02-24  0:00       ` Robert Dewar
  0 siblings, 1 reply; 25+ messages in thread
From: Jerome Desquilbet @ 1996-02-22  0:00 UTC (permalink / raw)


Robert Dewar wrote:
> for Ada files, and GNAT does not require specs to be explicitly
> compiled

Even GNAT will perform a semantic analysis of Ada specs. Try to run a
C++ compiler against a .h file!

  Jerome.




^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
  1996-02-21  0:00   ` Mark A Biggar
@ 1996-02-22  0:00     ` Norman H. Cohen
  0 siblings, 0 replies; 25+ messages in thread
From: Norman H. Cohen @ 1996-02-22  0:00 UTC (permalink / raw)


In article <4gg6da$8jk@wdl1.wdl.loral.com>, mab@dst17.wdl.loral.com
(Mark A Biggar) writes: 

|> Given the above example, is the following code legal, I have been unable to
|> determine if it is from the RM95: 
|>
|> with Parent.Child;
|> package My_Package is
|>
|>   A: Parent.Child.Auxiliary_Type;  -- or must I say A: Parent.Auxiliary_Type
|>
|> end My_Package;

No, it is illegal.  The effect of the with clause is as if you were
compiling My_Package in the following context: 

   package Parent is
      ...
      type Auxiliary_Type is ...;
      ...
      package Child is
         ...
      end Child;
   end Parent;

   package My_Package is
      ...
   end My_Package;

so you must say Parent.Auxiliary_Type.

|> If the above is illegal then it presents a problem if I have a library
|> level renaming of Parent.Child, like so: 
|>
|> package My_Child renames Parent.Child;
|>
|> with My_Child;
|> package Foo is
|>
|>   A: My_Child.Auxiliary_Type; -- LEGAL?
|>
|> end Foo;

Not legal, and there is no way to name Auxiliary_Type inside Foo, because
Parent is not visible there.  (AARM 10.1.2(9.b))  If you want to name an
entity exported by Parent (and not reexported), the name Parent must
appear in the with clause (possibly as a prefix).  This makes you write a
slightly longer with clause, but it is a very helpful property for
program readers trying to determine the origin of an entity named in Foo.

|> If this type of naming is legal then there is a simple emulation of
|> Norman's multi-part package proposal using child packages and a library
|> level rename.

It's not, but in any event my proposal allows a public part of a package
to refer to entities declared in an earlier private part of the package,
while still allowing the public part to be mentioned anywhere in a with
clause.  You can't do that with public and private children, because of
restrictions on where you can name private children in a with clause.

--
Norman H. Cohen    ncohen@watson.ibm.com




^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
  1996-02-21  0:00 ` John English
  1996-02-22  0:00   ` Nasser Abbasi
@ 1996-02-22  0:00   ` Gene Ouye
  1996-02-26  0:00     ` John English
  1 sibling, 1 reply; 25+ messages in thread
From: Gene Ouye @ 1996-02-22  0:00 UTC (permalink / raw)



John English <je@bton.ac.uk> wrote:
  [...]
> If the spec of Saving_Account has "with Account" at the beginning,
> "with Saving_Account" will imply "with Account". 

This is not true.  In order to compile and link the entire 
application, if you have a module "X" that with's Saving_Account, 
then X is indirectly dependent on Account (ie, you can't link X 
without having Account already compiled), but there is no implicit 
"with" that is included.  The with clause means you have visibility 
to declarations in referenced unit, in the above example, X, by 
withing Saving_Account has visibility to Saving_Account declaration, 
but NOT to Account declarations.

However, Saving_Account, because it with'ed Account, does have 
visibility to Account declarations.

> Or use child  packages: make Saving_Account a child of Account (e.g. 
> Account.Saving)  so that it is effectively an extension of Account.

This is true (as many others have demonstrated in this thread).

  [...]
> You can always put "subtype Money_Type is Account.Money_Type" in
> Saving_Account to make it directly usable from Saving_Account...

Yes, you can do this, but it probably won't do what I think you 
were intending.  You will have a Saving_Account.Money_Type that is
visible, but the values of the subtype may not be visible (if it's
numeric, then the numeric literals are directly convertible, but
if it's, say, an enumeration type, the enumeration literals aren't
made directly visible by a subtype declaration).  In any case, 
numeric type or no, the operations aren't brought along with a 
subtype declaration.  So you could assign numeric literals to 
objects of the subtype Saving_Account.Money_Type, but you couldn't 
invoke any operations on objects of that type unless you somehow
got visibility to them in Account (where they are declared).

Many have posted ways for this to be done, so there's no need for
me to get into them here...

If you're interested in religious language flame wars, you could
say that this is a case where Ada doesn't to what is expected.  But
if you understand what the subtype declaration really does, then this 
behavior really should be expected.  In other words, whether you're
doing C++ or Ada, you can't expect the language subtleties to be 
"expected" unless you get some education.

Gene Ouye <geneo@rational.com>






^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
  1996-02-21  0:00 ` John English
@ 1996-02-22  0:00   ` Nasser Abbasi
  1996-02-26  0:00     ` John English
  1996-02-22  0:00   ` Gene Ouye
  1 sibling, 1 reply; 25+ messages in thread
From: Nasser Abbasi @ 1996-02-22  0:00 UTC (permalink / raw)


In article <Dn4J2F.uI@bton.ac.uk>, je@bton.ac.uk (John English) says:
>
>Nasser Abbasi (nabbasi@qualcomm.com) wrote:
>: Lets also assume that we need to define a Money Type, defined in
>: the base class Account.     
>
>: In Ada95 this type is defined in the package Account.ads that also
>: includes the definition of the tagged record type Account (along with
>: operations that act on Account type).
>
>: Now, In Ada95, a client that wishes to use Saving_Account type (and
>: any operations on it) will "with" the Saving_Account Package.


>
>If the spec of Saving_Account has "with Account" at the beginning,
>"with Saving_Account" will imply "with Account". 

I do not think this is true. That is the main reason I asked the 
question in the first place. (I did not like having to "with" 
a package that was allready with'ed by a package I am "withing" ).

If what you say was the case, then types defined in package "A"
will be seen by clients to a package "B" where "B" has with'ed A. But
it is not so. Clients of "B" must also 'with' "A" to see types defined
in "A" even though "B: has allready  with'ed "A".

Thanks all for your inputs, I see 2 solutions now to this. I like the
child package solution mentioned by a number of people (including
John English).

I also like the fact that withing Ada packages is not transitive. when
I "with" Package A, only what is in A is visible, and not every thing
that in the chain of packages that A might have "withed" (unless 
offcourse tagged types are involved). This way seems to give better 
control of things. In C/C++ including files A.h, will also "pull" in
everthing that is included by A.h to the client level and make
these things visible at the client level.. 

Nasser





^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
  1996-02-20  0:00 ` Jerome Desquilbet
  1996-02-21  0:00   ` Robert Dewar
@ 1996-02-22  0:00   ` Pete Becker
  1996-02-23  0:00     ` Jerome Desquilbet
  1996-02-26  0:00     ` Darren C Davenport
  1 sibling, 2 replies; 25+ messages in thread
From: Pete Becker @ 1996-02-22  0:00 UTC (permalink / raw)


In article <3129F185.41C6@Rational.COM>, jDesquilbet@Rational.COM says...
>
>- you may have several different definitions for the same class in the
>same program, as long as they are never compiled together in the same
>compilation unit; example:
>
>#define private public // *** BERK! ***
>#include "...h"        // second definition for the same class
>#undef private

This is not true. A program that attempts to do this violates the one 
definition rule, so it is not a legal C++ program.
	-- Pete





^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
  1996-02-22  0:00   ` Pete Becker
@ 1996-02-23  0:00     ` Jerome Desquilbet
  1996-02-26  0:00     ` Darren C Davenport
  1 sibling, 0 replies; 25+ messages in thread
From: Jerome Desquilbet @ 1996-02-23  0:00 UTC (permalink / raw)


...YET ANOTHER RELIGIOUS WAR...

Pete Becker wrote:

> >#define private public // *** BERK! ***
> >#include "...h"        // second definition for the same class
> >#undef private
> 
> This is not true. A program that attempts to do this violates the one
> definition rule, so it is not a legal C++ program.

Pete,

What is this "one definition rule"? Could you point me to the
appropriate C++ Draft Standard location?

Try this:

// shape.h -----------------------------------------------------------

#ifndef SHAPE_H_
#define SHAPE_H_
class Shape {
  public:
    Shape();
    virtual void Draw  ()                         const = 0;
    virtual void Erase ()                         const = 0;
            void Move  (int Delta_X, int Delta_Y);
            void Rotate(int Delta_A);
  private:
    int X, Y, A;
};
#endif

// shape.C -----------------------------------------------------------

#include "shape.h"
#include <iostream.h>

Shape::Shape() {X=Y=A=0;}

void Shape::Move(int Delta_X, int Delta_Y) {
  cout << "I am a shape and I begin to move from ("
       << X << ',' << Y << ").\n";
  Erase(); X+=Delta_X; Y+=Delta_Y; Draw();
  cout << "I am a shape and I have finished moving to ("
       << X <<',' << Y << ").\n";
}
void Shape::Rotate(int Delta_A) {
  cout << "I am a shape and I begin to rotate from " << A << ".\n";
  Erase(); A+=Delta_A; Draw();
  cout << "I am a shape and I have finished rotating to " << A << ".\n";
}

// rectangle.h --------------------------------------------------------

#ifndef RECTANGLE_H_
#define RECTANGLE_H_
#include "shape.h"
class Rectangle : public Shape {
  public:
    Rectangle();
    void Draw  ()                         const;
    void Erase ()                         const;
    void Resize(int Delta_H, int Delta_W);
  private:
    int H, W;
};
#endif

// rectangle.C --------------------------------------------------------

#include "rectangle.h"
#include <iostream.h>

Rectangle::Rectangle() : Shape() {H=W=0;}

void Rectangle::Draw() const {
  cout << "I am a rectangle and I draw myself.\n";
}
void Rectangle::Erase() const {
  cout << "I am a rectangle and I erase myself.\n";
}
void Rectangle::Resize(int Delta_H, int Delta_W) {
  cout << "I am a rectangle and I begin to change my size.\n";
  Erase(); H+=Delta_H; W+=Delta_W; Draw();
  cout << "I am a rectangle and I have finished changing my size.\n";
}

// try_shape_rectangle_dirty_way.C ------------------------------------

#define private public // *** BERK! ***
#include "rectangle.h" // second definition for class Rectangle
#undef private        // in the program
int main() {
  Rectangle R;
  Shape*    pS;
  pS = &R;
  pS->X = 8;
  pS->Y = 18;
  pS->Move(10, 20);
}


It gives the following log:


I am a shape and I begin to move from (8,18).
I am a rectangle and I erase myself.
I am a rectangle and I draw myself.
I am a shape and I have finished moving to (18,38).


Note that the initial coordinates were (8,18).

The whole program contains two definitions for the same classes Shape
and Rectangle: for each, one definition with attributes private and
another definition with everything public.

It seems that in C++, every encapsulation can be legally broken,
essentially because of _independent_ compilation that allows
redefinitions of the same class.

Ada compilation model is different: it's _separate_ compilation.
Impossible in Ada to have a redefinition in the same program: it's
detected at compile-time. If something is checked in C++, it's deferred
to link-time (for example a redefinition of the same class that will
clash because the two constructors will have the same name).


Read also "The design and evolution of C++" by Bjarne Stroustrup,
chapter 17 "Namespaces", section 3 "Ideals for a solution": Ada has a
more complete solution than C++.

The basic property of OO languages is encapsulation. According to this
criteria, C++ fails.

Non mais enfin, quoi !


  Jerome.




^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
  1996-02-22  0:00     ` Jerome Desquilbet
@ 1996-02-24  0:00       ` Robert Dewar
  0 siblings, 0 replies; 25+ messages in thread
From: Robert Dewar @ 1996-02-24  0:00 UTC (permalink / raw)


Jerome said, answering me:

> for Ada files, and GNAT does not require specs to be explicitly
> compiled

Even GNAT will perform a semantic analysis of Ada specs. Try to run a
C++ compiler against a .h file!

Absolutely true. I was using compiled here in the sense of creating an
object file.

GNAT does not create object files for:

  subunits
  generic units
  package specs that require a body

However, it is perfectly fine, and very useful, to be able to compile
all these kinds of units using the -gnatc swich that asks GNAT to
fully check the syntax and semantics. It is indeed an important advantage
of Ada that such checking is possible (you said "try to run a C++ compiler
against a .h file", and of course a similar suggestion is "try to run a
C++ compiler against a template". In Ada, the generic contract model means
that a generic body that compiles clean will always instantiate clean, but
that of course is not the case for C++ templates. It is true that you get
some extra flexibility in return for this freedom in C++, but for the
construction of large systems, the contract model is an important guarantee
(so important that it is the one place in Ada 95 where an incompatible
change was made to Ada 83 to fix up the one serious hole in the model,
namely the business of passing unconstrained types).

In a small program with GNAT, you don't need to bother to compile 
these non-object-producing units at all, since you will find the
errors immediately from the clients, and can then fix up whatever
needs fixing.

But in a large program, the ability to verify specs, subunits, and generics
independently is critical (and required by the RM), so there the use of
the -gnatc switch is very useful.

Note: if you attempt to compile any of the above units to produce object
files (by omitting the -gnatc), then an error is signalled:

  No code generated for file xxx (package spec)

or somesuch. The error message is needed (and the compiler will indicate
error status) because the expected object file is not produced. Actually
I think I wll change the message to

  No object file created for file xxx (...)

since that is clearer. 

If you find this confusing, just follow the proper procedure, which is
to use -gnatc when compiling a subunit, generic unit, or package spec.
Note also that -gnatc is useful when comilling a parent unit with subunits,
it checks the syntax and semantics JUST of the parent unit, without checking
the subunits.





^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
  1996-02-26  0:00     ` Darren C Davenport
@ 1996-02-26  0:00       ` Pete Becker
  1996-02-27  0:00         ` Nigel Perry
  0 siblings, 1 reply; 25+ messages in thread
From: Pete Becker @ 1996-02-26  0:00 UTC (permalink / raw)


In article <4gspen$ot0@hacgate2.hac.com>, ddavenpo@redwood.hac.com says...
>
>Pete Becker (pete@borland.com) wrote:
>: In article <3129F185.41C6@Rational.COM>, jDesquilbet@Rational.COM says...
>: >
>: >- you may have several different definitions for the same class in the
>: >same program, as long as they are never compiled together in the same
>: >compilation unit; example:
>: >
>: >#define private public // *** BERK! ***
>: >#include "...h"        // second definition for the same class
>: >#undef private
>
>: This is not true. A program that attempts to do this violates the one 
>: definition rule, so it is not a legal C++ program.
>:       -- Pete
>
>We need to be careful here with terms used to describe C++ constructs.  
>A class name declaration is a C++ declaration (ARM C++ 3.1) not a definition.

This is a red herring. The issue is not about a "class name declaration", but 
about the actual definition of the class.

>This is what is specified in ".h" files.  There can be multiple declarations
>so the above code is legal C++ code.  

There can be multiple declarations of the name, but that is irrelevant.

>There can only be one definition
>of each object, function, class, and enumerator in a program and these
>are specified in ".cc" files.  Mr. Becker is correct about stating that
>there must be only one definition but that rule does not apply in this
>instance.

No, my original statement is correct: a program which contains multiple 
definitions of the same class is not a valid C++ program because it violates 
the one definition rule. That is exactly the case that the original message 
attempts to create, as indicated by the prefatory text which says "you may 
have several different definitions for the same class in the same program, as 
long as they are never compiled together in the same compilation unit" and by 
the comment that says "second definition for the same class". You MAY NOT have 
several definitions for the same class in the same program. Changing private 
members to public creates a different definition of the class and is illegal. 
Class definitions are not local to a compilation unit, and cannot be treated 
so cavalierly. There aren't many compilers that enforce this rule, but it is 
nevertheless a constraint on valid C++ programs.
	-- Pete





^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
@ 1996-02-26  0:00 Simon Johnston
  0 siblings, 0 replies; 25+ messages in thread
From: Simon Johnston @ 1996-02-26  0:00 UTC (permalink / raw)


> ...YET ANOTHER RELIGIOUS WAR...

Lets hope not.

> Pete Becker wrote:
>
> > >#define private public // *** BERK! ***
> > >#include "...h"        // second definition for the same class
> > >#undef private
> >
> > This is not true. A program that attempts to do this violates the one
> > definition rule, so it is not a legal C++ program.
>
> Pete,
>
> What is this "one definition rule"? Could you point me to the
> appropriate C++ Draft Standard location?

  [snip]

> The whole program contains two definitions for the same classes Shape
> and Rectangle: for each, one definition with attributes private and
> another definition with everything public.

The whole program does, the point is that no one single compilation stream
must include more than one definition for a given entity.

> It seems that in C++, every encapsulation can be legally broken,
> essentially because of _independent_ compilation that allows
> redefinitions of the same class.
>
> Ada compilation model is different: it's _separate_ compilation.
> Impossible in Ada to have a redefinition in the same program: it's
> detected at compile-time. If something is checked in C++, it's deferred
> to link-time (for example a redefinition of the same class that will
> clash because the two constructors will have the same name).
>
>
> Read also "The design and evolution of C++" by Bjarne Stroustrup,
> chapter 17 "Namespaces", section 3 "Ideals for a solution": Ada has a
> more complete solution than C++.
>
> The basic property of OO languages is encapsulation. According to this
> criteria, C++ fails.
>
> Non mais enfin, quoi !
>
>
>   Jerome.
>
>

with StandardDisclaimer; use StandardDisclaimer;
package Sig is
--,-------------------------------------------------------------------------.
--|Simon K. Johnston - Development Engineer (C++/Ada95) |ICL Retail Systems |
--|-----------------------------------------------------|3/4 Willoughby Road|
--|Unix Mail: skj@acm.org                               |Bracknell          |
--|Telephone: +44 (0)1344 476320 Fax: +44 (0)1344 476302|Berkshire          |
--|Internal : 7261 6320   OP Mail: S.K.Johnston@BRA0801 |RG12 8TJ           |
--|WWW URL  : http://www.acm.org/~skj/                  |United Kingdom     |
--`-------------------------------------------------------------------------'
end Sig;




^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
  1996-02-22  0:00   ` Nasser Abbasi
@ 1996-02-26  0:00     ` John English
  1996-02-27  0:00       ` Dale Stanbrough
  0 siblings, 1 reply; 25+ messages in thread
From: John English @ 1996-02-26  0:00 UTC (permalink / raw)


Nasser Abbasi (nabbasi@qualcomm.com) wrote:
: In article <Dn4J2F.uI@bton.ac.uk>, je@bton.ac.uk (John English) says:
: >If the spec of Saving_Account has "with Account" at the beginning,
: >"with Saving_Account" will imply "with Account". 

: I do not think this is true. That is the main reason I asked the 
: question in the first place. (I did not like having to "with" 
: a package that was allready with'ed by a package I am "withing" ).

Hmm.  I've been having another look at the visibility rules in the LRM and,
as usual, they've made my head go round and round :-)

Certainly GNAT allows you to reference Account.X if you have "with
Saving_Account" (but I'm all too aware that GNAT /= Ada95 :-), although
the same is not true for "use" clauses ("use Saving_Account" does not
imply "use Account").  Remember that I'm talking about *with clauses in
package specifications* and not use clauses *or* package bodies (in case
there is any confusion about this).

: If what you say was the case, then types defined in package "A"
: will be seen by clients to a package "B" where "B" has with'ed A. But
: it is not so. Clients of "B" must also 'with' "A" to see types defined
: in "A" even though "B: has allready  with'ed "A".

If you're right this would be a real pain.  Clients of a package would have
to know (recursively) what other packages the spec(s) reference; if the
spec for X "withs" a package Y so it can use type Y.T as a procedure
parameter then you wouldn't be able to use X without Y (i.e. "with X"
on its own would be useless; you'd have to have "with X, Y" and probably
other things as well if Y has any "with" clauses in its specification.

This is such a horrible concept that I'm inclined to believe GNAT, but
if anyone who can understand all the subleties of the visibility rules
can give us all a definitive explanation in words of sufficiently few
syllables that Bears of Very Little Brain like me can understand, I for
one would be profoundly grateful.

-- 
----------------------------------------------------------------------------
John English <je@brighton.ac.uk>, Dept. of Computing, University of Brighton
  "Disks are divided into sex and tractors..."
----------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
  1996-02-22  0:00   ` Gene Ouye
@ 1996-02-26  0:00     ` John English
  0 siblings, 0 replies; 25+ messages in thread
From: John English @ 1996-02-26  0:00 UTC (permalink / raw)


Gene Ouye (geneo@rational.com) wrote:
: If you're interested in religious language flame wars, you could
: say that this is a case where Ada doesn't to what is expected.  But
: if you understand what the subtype declaration really does, then this 
: behavior really should be expected.  In other words, whether you're
: doing C++ or Ada, you can't expect the language subtleties to be 
: "expected" unless you get some education.

Ooooooh! :-)

-- 
----------------------------------------------------------------------------
John English <je@brighton.ac.uk>, Dept. of Computing, University of Brighton
  "Disks are divided into sex and tractors..."
----------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
  1996-02-22  0:00   ` Pete Becker
  1996-02-23  0:00     ` Jerome Desquilbet
@ 1996-02-26  0:00     ` Darren C Davenport
  1996-02-26  0:00       ` Pete Becker
  1 sibling, 1 reply; 25+ messages in thread
From: Darren C Davenport @ 1996-02-26  0:00 UTC (permalink / raw)


Pete Becker (pete@borland.com) wrote:
: In article <3129F185.41C6@Rational.COM>, jDesquilbet@Rational.COM says...
: >
: >- you may have several different definitions for the same class in the
: >same program, as long as they are never compiled together in the same
: >compilation unit; example:
: >
: >#define private public // *** BERK! ***
: >#include "...h"        // second definition for the same class
: >#undef private

: This is not true. A program that attempts to do this violates the one 
: definition rule, so it is not a legal C++ program.
: 	-- Pete

We need to be careful here with terms used to describe C++ constructs.  
A class name declaration is a C++ declaration (ARM C++ 3.1) not a definition.
This is what is specified in ".h" files.  There can be multiple declarations
so the above code is legal C++ code.  There can only be one definition
of each object, function, class, and enumerator in a program and these
are specified in ".cc" files.  Mr. Becker is correct about stating that
there must be only one definition but that rule does not apply in this
instance.

Darren Davenport





^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
  1996-02-26  0:00       ` Pete Becker
@ 1996-02-27  0:00         ` Nigel Perry
  0 siblings, 0 replies; 25+ messages in thread
From: Nigel Perry @ 1996-02-27  0:00 UTC (permalink / raw)


In article <4gt3ag$76m@druid.borland.com>, pete@borland.com (Pete Becker) wrote:

<snip>
>No, my original statement is correct: a program which contains multiple 
>definitions of the same class is not a valid C++ program because it violates 
>the one definition rule. That is exactly the case that the original message 
<snip>
>so cavalierly. There aren't many compilers that enforce this rule, but it is 
>nevertheless a constraint on valid C++ programs.

C++ Draft Standard: 3.2 One defintion rule, clause 8:

No diagnostic is required for a violation of the ODR rule.

Similarly, 3.5 Program and linkage, clause 9 ends:

A violation of this rule on type identity does not require a diagnostic

[also many other places in the Standard]

What does this mean. Well Pete may be right (I haven't checked) that the
code is "wrong", but "wrong" code does not require a diagnostic in C++.
The opposite of a diagnostic is surely a succesful compile & link (but not
necessarily a succesful execution!), so "wrong" code meets the Standard...
My guess is that defining "private" as "public" to break encapsulation
isn't forbidden by the Standard - if it was then it wouldn't be C/C++
would it? :-)

Don't people use C/C++ so they *can* break the rules? If you want strict type
checking etc. go use Ada 95, Haskell, SML, etc. etc. etc.

Just my 2c's worth :-)

-- 
Dr Nigel Perry                  Email: N.Perry@massey.ac.nz
Department of Computer Science  Tel:   +64 6 350 4007
Massey University               Fax:   +64 6 350 5611 Attn. Dr N. Perry
Palmerston North                Ftp/Gopher: smis-asterix.massey.ac.nz
New Zealand                        (Mac software/Research papers)

The Cycle Helmet Law: New Zealand's Shame, Speeding before children :-(
                      Prevention is better than padding!




^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
  1996-02-26  0:00     ` John English
@ 1996-02-27  0:00       ` Dale Stanbrough
  0 siblings, 0 replies; 25+ messages in thread
From: Dale Stanbrough @ 1996-02-27  0:00 UTC (permalink / raw)


John English, je@bton.ac.uk writes:
": If what you say was the case, then types defined in package "A"
: will be seen by clients to a package "B" where "B" has with'ed A. But
: it is not so. Clients of "B" must also 'with' "A" to see types
defined
: in "A" even though "B: has allready  with'ed "A".

If you're right this would be a real pain.  Clients of a package would
have
to know (recursively) what other packages the spec(s) reference; if the
spec for X "withs" a package Y so it can use type Y.T as a procedure
parameter then you wouldn't be able to use X without Y (i.e. "with X"
on its own would be useless; you'd have to have "with X, Y" and
probably
other things as well if Y has any "with" clauses in its specification.

This is such a horrible concept that I'm inclined to believe GNAT, but
if anyone who can understand all the subleties of the visibility rules
can give us all a definitive explanation in words of sufficiently few
syllables that Bears of Very Little Brain like me can understand, I for
one would be profoundly grateful."

Au Contraire, it's a great concept. It is SO nice to be able to see,
from the top of a listing, just what the relationship b/w the unit 
you are looking at to the rest of the system is.

I *hate* transtive 'with'ing relationships! When you read the code
of C/C++, you may have one #include at the top, but your code
references
all sorts of types/functions etc. Where do they come from? What range
of packages do I have to look at before I can find the declarations?
Should I do a broad search, or a depth first search on the #include
files
when looking for the declarations?
In Ada, with it's 'flat' view of 'with'ings (compared to C's deep
#include
model) you can easily see the level of coupling of a
package/compilation
unit.

A simple explanation is perhaps...

	"with"ing never extends beyond the units you have explicity "with"ed.
	If you need something that they have "with"ed, then you have to 
	with it as well. "With"ing is only ever one unit deep.
	
A simple example
	----------------------------------
	package a is
		type alpha is...
		
		function X return alpha;
	end a;
	
	----------------------------------
	with a;
	package b is
		type beta is
		
		procedure Y(item:       alpha);
		procedure Z(item:in out beta);
	end b;
	
	----------------------------------
	-- if you use resources from A,		-- If you don't use resources from
	-- then you have to "with" A.		-- A, then you can ignore it.
	with A;
	with B;								with B;
		
	procedure main is					procedure main is
		stuff	:A.alpha	:= A.X;			stuff	:B.beta;
	begin								begin
		B.Y(stuff);							B.Z(stuff);
	end;								end;
	
Important to note that if procedure main isn't going to declare any
alpha values, or call B.Y, then it doesn't need to with A at all.

The fact that B has "with"ed A can be viewed as a compositional
legacy from the construction of B. It has little to do with how
procedure main is constructed.

If "main" want's to use resources from A, then it explicity has to
declare it's intent for all the world to see.

The use clause only means you don't have to use dot notation (e.g.
B.Y) when accessing resources from the package.

I suspect that if you examine some real code that you will not
find too great a list of "with"ed units (esp. with well designed
code). Even if it were, I wouldn't be too concerned, as it aids
the reader of the code.


Dale




^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: on OO differnces between Ada95 and C++
  1996-02-20  0:00 ` Norman H. Cohen
  1996-02-21  0:00   ` Mark A Biggar
@ 1996-02-27  0:00   ` Adam Morris
  1 sibling, 0 replies; 25+ messages in thread
From: Adam Morris @ 1996-02-27  0:00 UTC (permalink / raw)


In article <4gdidj$10f5@watnews1.watson.ibm.com>,
   ncohen@watson.ibm.com (Norman H. Cohen) wrote:
>In article <4gbq7q$g08@qualcomm.com>, nabbasi@qualcomm.com (Nasser Abbasi)
>observes that in C and C++ one specifies an interface in a .h (or .H)
>file and imports the interface with a #include directive, while in Ada
>one specifies an interface with a program-unit declaration (typically a
>package declaration) and imports it with a with clause.  In C and C++
>importing is transitive--if B #includes A and C #includes B, then C has
>effectively #included--while in Ada it is not--if B has a with clause for
>A and C has a with clause for B, then A is not visible in C unless C has
>its own explicit with clause for A.

Only if you do what you shouldn't do...  the .h file should have forward 
declarations of all classes it uses except in certain cases.  And what are 
those cases, if A inherits from B then (and only then as far as I know) should 
you #include B.h in A.h  otherwise you have a declaration saying
class B{};

you #include B.h in the .cc file this means that A.cc knows about B.h but C.cc 
will only know about B.h if it has included A.h AND A is derived from B.

Adam.




^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~1996-02-27  0:00 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1996-02-21  0:00 on OO differnces between Ada95 and C++ Christian Jaensch, FRG
  -- strict thread matches above, loose matches on Subject: below --
1996-02-26  0:00 Simon Johnston
1996-02-20  0:00 Nasser Abbasi
1996-02-20  0:00 ` Robert I. Eachus
1996-02-20  0:00 ` Norman H. Cohen
1996-02-21  0:00   ` Mark A Biggar
1996-02-22  0:00     ` Norman H. Cohen
1996-02-27  0:00   ` Adam Morris
1996-02-20  0:00 ` Jerome Desquilbet
1996-02-21  0:00   ` Robert Dewar
1996-02-22  0:00     ` Jerome Desquilbet
1996-02-24  0:00       ` Robert Dewar
1996-02-22  0:00   ` Pete Becker
1996-02-23  0:00     ` Jerome Desquilbet
1996-02-26  0:00     ` Darren C Davenport
1996-02-26  0:00       ` Pete Becker
1996-02-27  0:00         ` Nigel Perry
1996-02-21  0:00 ` Jon S Anthony
1996-02-21  0:00 ` John English
1996-02-22  0:00   ` Nasser Abbasi
1996-02-26  0:00     ` John English
1996-02-27  0:00       ` Dale Stanbrough
1996-02-22  0:00   ` Gene Ouye
1996-02-26  0:00     ` John English
1996-02-21  0:00 ` Darren C Davenport

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox