When, why and where should a struct be used?

  • Thread starter Thread starter clintonG
  • Start date Start date
Bruce Wood said:
OK... maybe I'm being a dunce, here. One of my half-dead C++ brain
cells just told me that this can be done with _any_ type: just declare
a variable as being of that type rather than a pointer to that type.

Exactly - that's where I was coming from when I suggested that C#
structs were like C++ classes in some ways. Of course, you can't derive
from a C# struct, so in that sense they're totally different :)
Regardless, one thing I'm sure of is that in C++ classes and structs
are essentially the same thing, just that structs are sort of
"class-lite".

Sort of. From what I remember, structs in C++ can't have methods, so
they don't have vtables etc.
This is absolutely not so in C#: structs act very
differently from classes, so much so that I would say that the C#
"struct" is a brand new beast that really doesn't have a parallel in
C++.

Agreed.
 
Jon Skeet said:
I thought you couldn't put methods in a struct in C++?

Sure you can.
In C you can't, but in C++...sure thing.
Actually in C you can put function pointers in structs, but they have no knowledge of *this* so they
are less useful than the C++ variant.

I am not sure why people think classes are more heavyweight than structs in C++.

Mostly due to common usage I would guess

Bill
 
...
Bruce Wood wrote:

Sort of. From what I remember, structs in C++ can't have methods, so
they don't have vtables etc.

As Bill previously said, the only difference in C++ between structs and
classes is the visibility of their members.

This is one point I usually make to programmers coming from C to C++; they
expect the same code to be compilable in either language, but they often
miss that it can result in performance hits, as when using structs they'll
be *instantiated*, running default constructors, because they're really
classes.


// Bjorn A
 
Jon Skeet said:
I thought you couldn't put methods in a struct in C++?

Sure you can.
And you are OK with packing UNLESS you have virtual methods, a virtual base
class or multiple inheritance which introduce the vtbl pointer ( I think
that the spec may actually say that you can't rely on the layout of a class
at all for these reasons but in practice it will be the same as a struct if
you avoid the above.
 
As Bill previously said, the only difference in C++ between structs and
classes is the visibility of their members.
Well, *again*: only nearly correct.

structs and classes differ in

1.) default visibility of members. Of course, private/protected/public
can be used in both to make the accessability whatever you want.

so, there is *no* difference between

class A
{
public:
int i;
};

and

struct A
{
int i;
};

concerning member access.




2.) default inheritance for structs is public, while for class it is
private.

so, for a type A

class B : A { ...};

means

class B : public A { ... };

if A is a struct, but means

class B : private A { ... };

if A is a class.

In C++ he class/struct does not say whether we have value or reference
semantics. ANY type in C++ can be used as value type or reference
type.

For any type T

T t; // defines a value of type T on the stack.

while

T* and T& denote reference types (pointer is considered ref
type too, here, although it really is a special case)



Hope that helps.
Martin
 
Bjorn Abelli said:
As Bill previously said, the only difference in C++ between structs and
classes is the visibility of their members.

Righto. Good job I don't have to do much C++, isn't it? :)

Always good to keep learning...
 
I've sure learned a lot from this topic and for now I have enough on my
hands to master class design. As developers adopt WPF and the use of XAML it
seems to me that the struct will once again become a significant design
element.

<%= Clinton Gallagher
 
Well, *again*: only nearly correct.

structs and classes differ in

1.) default visibility of members. Of course, private/protected/public
can be used in both to make the accessability whatever you want.

Yes, that's what I meant, but I missed to write out the little word
"default" before the word "visibility"... ;-)

// Bjorn A
 
Bruce Wood said:
Well, as I said in the other thread. 99.9% of the time you want a
class.
You want a struct when you want the thing to act like a primitive
type...

I think there's another good reason. If I do

MyClass x = obj.GetInfo();

to obtain some richly structured piece of information about "obj",
sometimes I want the recipient to know that the thing "x" they
retrieve will not change despite further changes to "obj". Structs are
the only way to tell them this in a way that's enforced by the
compiler. Otherwise, if I return a class reference, I have to just
communicate the same fact through comments.

Personally I end up wanting to do this a lot, because I come from a
functional-programming language background where it's a ubiquitous
idiom.
 
Lucian Wischik said:
I think there's another good reason. If I do

MyClass x = obj.GetInfo();

to obtain some richly structured piece of information about "obj",
sometimes I want the recipient to know that the thing "x" they
retrieve will not change despite further changes to "obj". Structs are
the only way to tell them this in a way that's enforced by the
compiler. Otherwise, if I return a class reference, I have to just
communicate the same fact through comments.

Well, that only works if the struct doesn't contain any reference types
- if it does, they could still change.

Another way of doing this is to make the returned object immutable.
Immutable types are very handy, although they come with their own
problems, of course.
 
Jon Skeet said:
[the recipient to know that the thing "x" they retrieve will not change]

Another way of doing this is to make the returned object immutable.
Immutable types are very handy, although they come with their own
problems, of course.

How? I mean, I don't see any language support for demonstrating to the
recipient of an object that this object is immutable. Sure, you can
give them a ReadOnlyCollection<T> or an IEnumerable<T> so that *they*
can't alter it. But this doesn't assure them that *you're* not going
to alter it.
 
I don't see any language support for demonstrating to the recipient of an object that this object is immutable.

If its properties have no setters, and its methods don't change its
state, then it's immutable. I have many classes like this: their state
is set upon construction, and then never altered. If I want an altered
version, I have to construct a new one using the existing one as a
template.
 
Bruce Wood said:
If its properties have no setters, and its methods don't change its
state, then it's immutable.

and it's sealed.

Although... doing this, for instance, forces you to expose all details
about what you give back -- you can't give back an ICollection, for
instance.
 
Although... doing this, for instance, forces you to expose all details
about what you give back -- you can't give back an ICollection, for
instance.

? I'm not sure I understand? ...No, I'm quite sure I don't understand.
:-)

Could you elaborate?
 
and it's sealed.

No, it doesn't even have to be sealed, so long as all fields are
private, there are no setters, and nothing is virtual, which gives
child classes no more access than the public. You could never make a
child class that altered the state of the base object, so long as you
access the properties / methods via a base class reference. Once it's
instantiated, you can't change its state.

If it's not sealed, you could create a child class that adds more
state, and that additional state may be mutable. The child class could
even hide some base class properties using "new" and make them mutable,
but only when a client is working with the child instance through a
child class reference. If you cast the reference to the base class you
will always be back to the immutable object, the way it was when it was
constructed.
 
Bruce Wood said:
? I'm not sure I understand? ...No, I'm quite sure I don't understand.
:-) Could you elaborate?

How does a user of my object know that it's immutable? -- if I give
him just an interface to it, there's no way he can know, none at all.
Even if the object has all private fields and no methods are virtual
and there are no "setters", he still has to look at the source code or
read the comments for the object's methods to know that they won't
alter the state of the object.
 
Bruce... ??? Classes in C++ use, by default, value semantics. In C++,
when you
declare an object, an object is created (value semantics). Hence the
need, except
in trivial cases, to write a user defined copy constructor. If you don't
write a copy
constructor, the compiler will write one for you.

Regards,
Jeff
Argument passing aside, every type you
create in C++ is a reference type<
 
How does a user of my object know that it's immutable? -- if I give
him just an interface to it, there's no way he can know, none at all.
Even if the object has all private fields and no methods are virtual
and there are no "setters", he still has to look at the source code or
read the comments for the object's methods to know that they won't
alter the state of the object.

Going back to your original observation, no, there is no language
support to demonstrate that an object is immutable. It's not part of
the contract (if you will) that's stated in the C# language. It is, as
you have observed, part of the contract you make when you describe what
your class does. For better or worse, there are a lot of things not
guaranteed by the C# language itself, on which you have to trust the
person who wrote the comments.

When Jon said, "...another way is to make the returned object
immutable..." he didn't mean that you, as a consumer of a type, could
do something to guarantee that the type was immutable. Neither did he
mean that you, as the writer of a type, could do something to prove to
any consumer that it was immutable. I think that he meant "make [it]
immutable" in the sense that you write the code for the type so that
its state is established in its constructor and then no property or
method ever alters it, and then you write comments to the effect that
this type is immutable.

I'm still not sure what this has to do with properties returning
ICollections, but sometimes I can be rather thick about things.... :-)
 
Yeah, that's why immediately afterwards I posted that I thought maybe I
was being a dunce. I was. My apologies. :-(
 
Bruce Wood said:
Going back to your original observation, no, there is no language
support to demonstrate that an object is immutable.

My original observation was that, yes, there is language support to
demonstrate that a function returns you an "immutable" thing, in the
sense that the function will no longer alter it -- make it return a
struct! So that counts (as per thread title) of an instance "when why
and where" a struct should be used. It's for when your design calls
for something immutable by the sender, and you want it robustly
compiler-supportedly immutable against the possibility of later
programmer mistakes. (and sometimes just when the weight of putting
every single field into the constructor is too much...)

I'm still not sure what this has to do with properties returning
ICollections

I think it's interesting that, if a function returns IEnumerable<T>,
then it gives a compiler-supported guarantee that the *recipient* will
not subsequently alter the list. But it's impossible for any choice of
interface to make similar guarantees about the *sender*.
 
Back
Top