Do you use const member a lot?

B

Ben

For many times, I've found myself changing my member variables from
const back to non-const. No matter how good the original objective
was, there was always at least one reason not to use const members.
(swap, storing it in a container, etc.)
Whereas in Java, 80% of the case, I would want "final" for my instance
variables.

It makes me think that is "const member variable" ever useful in C++?

Maybe because of the value semantics of C++ objects, immutable
programming is just not good for C++.

static const is useful, const methods are useful, const parameters are
useful, const T* is useful, but just cannot find niches for const
member variables.

So, what would you use const instance member variable for? Do you use
it at all?
 
P

Phlip

Ben said:
For many times, I've found myself changing my member variables from
const back to non-const. No matter how good the original objective
was, there was always at least one reason not to use const members.
(swap, storing it in a container, etc.)
Whereas in Java, 80% of the case, I would want "final" for my instance
variables.

It makes me think that is "const member variable" ever useful in C++?

You have discovered that refactoring and re-featurizing are good.

Program designs are never immutable. Aspects like 'const' or non-virtual can
ensure that when you upgrade, you can lower the odds of breaking abilities.
Start with the weakest constructions possible - constants, references,
delegation - and only refactor towards mutables, pointers or inheritance as
you find a need.
 
M

Mike Wahler

Ben said:
For many times, I've found myself changing my member variables from
const back to non-const. No matter how good the original objective
was, there was always at least one reason not to use const members.
(swap, storing it in a container, etc.)
Whereas in Java, 80% of the case, I would want "final" for my instance
variables.

It makes me think that is "const member variable" ever useful in C++?

Maybe because of the value semantics of C++ objects, immutable
programming is just not good for C++.

static const is useful, const methods are useful, const parameters are
useful, const T* is useful, but just cannot find niches for const
member variables.

So, what would you use const instance member variable for? Do you use
it at all?

Some very old sage advice:

When encountering a new tool, don't waste your time
going around trying to find an application for it.

Decide what you need to do, then locate the tools
best suited for that task. While looking for the
right tools, if you see some that don't fit your
task, just leave them in the box.


-Mike
 
E

EventHelix.com

So, what would you use const instance member variable for? Do you use
it at all?

In the code I work with, I haven't seen a lot of const member variables.
I do see const methods and parameters being used a lot.

I guess there are few cases where a member variable can be initialized
in the constructor and does not need to change for the lifetime of the
object.

Sandeep
 
J

JKop

Ben posted:
For many times, I've found myself changing my member variables from
const back to non-const. No matter how good the original objective
was, there was always at least one reason not to use const members.
(swap, storing it in a container, etc.)
Whereas in Java, 80% of the case, I would want "final" for my instance
variables.

It makes me think that is "const member variable" ever useful in C++?

Maybe because of the value semantics of C++ objects, immutable
programming is just not good for C++.

static const is useful, const methods are useful, const parameters are
useful, const T* is useful, but just cannot find niches for const
member variables.

So, what would you use const instance member variable for? Do you use
it at all?


class BankAccount
{
protected:

const unsigned long account_number;

public:

BankAccount(unsigned long in_account_number) : account_number
(in_account_number) { ; }

};




-JKop
 
T

Thomas Matthews

Ben wrote:
[snip]
So, what would you use const instance member variable for? Do you use
it at all?
I use const member variables for {named} constants
used only within the class, member function or
global function.


--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book
http://www.sgi.com/tech/stl -- Standard Template Library
 
B

Ben

class BankAccount
{
protected:

const unsigned long account_number;

public:

BankAccount(unsigned long in_account_number) : account_number
(in_account_number) { ; }

};




-JKop

This is similar to the stuff I normally start with. It looks innocent
to have "const member" here. However, later, you will find it hard to
store in a vector or an array. Users may complain it is hard to
aggregate your BankAccount object into their own objects when they do
want to change the bankaccount attribute.
In short, this BankAccount is only good for use as a stack object,
nothing else. And very rarely you will feel satisfied with that.

Again, it is the value semantics that kills the attempt to be
immutable.

In java, even your object is immutable, users can always do functional
update to get a new value if they want. And I do like that style. But
this is not possible in C++.

So, I'd like to conclude that "immutable programming" is dead in C++
and "const member variable" is very rarely useful or just useless.
 
J

JKop

Ben posted:
This is similar to the stuff I normally start with. It looks innocent
to have "const member" here. However, later, you will find it hard to
store in a vector or an array. Users may complain it is hard to
aggregate your BankAccount object into their own objects when they do
want to change the bankaccount attribute.
In short, this BankAccount is only good for use as a stack object,
nothing else. And very rarely you will feel satisfied with that.

Again, it is the value semantics that kills the attempt to be
immutable.

In java, even your object is immutable, users can always do functional
update to get a new value if they want. And I do like that style. But
this is not possible in C++.

So, I'd like to conclude that "immutable programming" is dead in C++
and "const member variable" is very rarely useful or just useless.


I was getting at something like the following:

In a bank, the one sole piece of data by which a bank account is identified
is the account_number. After that, things like Balance and Account Holder
are just supplemental bits of data. You cannot change an account's number,
to do so would be change the one piece of data by which the account can be
identified. You would have to close the account and open a new one, which
would have a new unique number.

class BankAccount
{
protected:

const unsigned long int account_number;
char account_holder[30];

public:

BankAccount(char* in_account_holder) : account_number
(GenerateUniqueAccountNumber())
{
strcpy(in_account_holder, account_holder);
}

};


I know that my example is a bit crappy and you'd never have a class like so
or anything, but I hope it shows what I'm getting at.


-JKop
 
J

Jerald Fijerald

It makes me think that is "const member variable" ever useful in C++?

It is very useful if you tend to see objects as alogrithms (and not as
factories, trains, railroads, baboons, etc).

For example, an algorithm:

class Algorithm
{
void f1 (); // calls f2
void f2 (); // calls f1
int common_data_of_f1_and_f2;
public:
int result;
Algorithm (parameters); // calls f1 to get started
};

And that is used in a function

int foo ()
{
Algorithm A (UserTree, 123);
return A.result;
}

In such cases it makes sense to have const members for
puproses of optimization.

Best regards,

Gerald
 
B

Ben

In a bank, the one sole piece of data by which a bank account is identified
is the account_number. After that, things like Balance and Account Holder
are just supplemental bits of data. You cannot change an account's number,
to do so would be change the one piece of data by which the account can be
identified. You would have to close the account and open a new one, which
would have a new unique number.

class BankAccount
{
protected:

const unsigned long int account_number;
char account_holder[30];

public:

BankAccount(char* in_account_holder) : account_number
(GenerateUniqueAccountNumber())
{
strcpy(in_account_holder, account_holder);
}

};

I understand that there are many business logics that require certain
field to be const or certain objects to be read-only.

The question is: is it wise to do that with "const member"? You are
sure your object will never be stored in a vector?
You are sure users never want to aggregate your object?

Yes, "this field should not change", but that can be implemented in
many ways. In c++, it is hard to say that something can never change.
Whatever the business requirement is, you may just want to be able to
change it for implementation reasons such as performance or
convenience. Say, swap.

class MyObject{
BankAccount acc;
void swap(MyObject& other){
//how do I write this if I cannot change acc?
}
};

How exactly users want to use this class should be decided by the
user. It sounds to me a too brave decision for the class designer to
say "no, I don't want it to be in a container. And no, don't aggregate
me!"

It makes more sense to say it cannot change in certain modules or
places or time, which, can be achieved by means of private/protected
and adapters.

Is it worthwhile to sacrifice flexibility for "security"? Talking
about security, with pointer arithmetics and casting present, nothing
is real secure anyway.

Well. it now sounds more something about personal flavor. One may
insist that he does not care the so-called "flexibility" and changing
one field is simply unacceptable, period. I have no disregard against
such decision.

I myself just always found I had to go back and change that decision,
however innocent it looked originally.
 
I

Ingo Nolden

I was getting at something like the following:

In a bank, the one sole piece of data by which a bank account is
identified is the account_number. After that, things like Balance and
Account Holder are just supplemental bits of data. You cannot change
an account's number, to do so would be change the one piece of data by
which the account can be identified. You would have to close the
account and open a new one, which would have a new unique number.

class BankAccount
{
protected:

const unsigned long int account_number;
char account_holder[30];

public:

BankAccount(char* in_account_holder) : account_number
(GenerateUniqueAccountNumber())
{
strcpy(in_account_holder, account_holder);
}

};


I know that my example is a bit crappy and you'd never have a class
like so or anything, but I hope it shows what I'm getting at.


-JKop

I also think that a const member is sometimes useful. I have one application for it in my self
made Type inquiry. There is a Type class with some const members that hold the information of
the type, like the baseclass, the name string and a unique code. Then there ist a constructor,
that defines them similar to the bank account example above. Finally I have a const static
member for every type in the library that looks like that:
static const Type Polynom;

and

const Type Type::polynom = Type( 0xff0f0f0f, "Polynom", &ObjectBase );

The constructor arguments are the values for the const members.

I don't know about compiler optimization issues, but for me it is the information that const
gives to the programmer. When I take an objects type code like pDerivedPoly->GetType( )->Code
then its good to see it is const so it is not for change and it cannot be changed
accidentially.

But, I didn't find this by looking for a purpose for const members, so it is probably true to
say don't look for purposes for your tools, look for the tools you have a purpose for.
On the other hand, if you don't try and get to know all possibilities ( tools in your box ),
how can you know you choose the best one in a langluage that offers many ways to do the same
thing.

cheers
Ingo
 
J

JKop

Ben posted:
In a bank, the one sole piece of data by which a bank account is
identified is the account_number. After that, things like Balance and
Account Holder are just supplemental bits of data. You cannot change
an account's number, to do so would be change the one piece of data by
which the account can be identified. You would have to close the
account and open a new one, which would have a new unique number.

class BankAccount
{
protected:

const unsigned long int account_number;
char account_holder[30];

public:

BankAccount(char* in_account_holder) : account_number
(GenerateUniqueAccountNumber())
{
strcpy(in_account_holder, account_holder);
}

};

I understand that there are many business logics that require certain
field to be const or certain objects to be read-only.

The question is: is it wise to do that with "const member"? You are
sure your object will never be stored in a vector?
You are sure users never want to aggregate your object?

Yes, "this field should not change", but that can be implemented in
many ways. In c++, it is hard to say that something can never change.
Whatever the business requirement is, you may just want to be able to
change it for implementation reasons such as performance or
convenience. Say, swap.

class MyObject{
BankAccount acc;
void swap(MyObject& other){
//how do I write this if I cannot change acc?
}
};

How exactly users want to use this class should be decided by the
user. It sounds to me a too brave decision for the class designer to
say "no, I don't want it to be in a container. And no, don't aggregate
me!"

It makes more sense to say it cannot change in certain modules or
places or time, which, can be achieved by means of private/protected
and adapters.

Is it worthwhile to sacrifice flexibility for "security"? Talking
about security, with pointer arithmetics and casting present, nothing
is real secure anyway.

Well. it now sounds more something about personal flavor. One may
insist that he does not care the so-called "flexibility" and changing
one field is simply unacceptable, period. I have no disregard against
such decision.

I myself just always found I had to go back and change that decision,
however innocent it looked originally.

Could you please elaborate on how putting into into a container class could
complicate things? I've seen simple container classes before and all they do
is store a load of pointers to seperate objects. How will this intefer with
a const data member?!

-JKop
 
P

Peter van Merkerk

Thomas Matthews said:
I use const member variables for {named} constants
used only within the class, member function or
global function.

Why not make those static const members?

FWIW I share the observations made by the OP ("static const is useful,
const methods are useful, const parameters are useful, const T* is useful,
but just cannot find niches for const member variables").
 
T

tom_usenet

For many times, I've found myself changing my member variables from
const back to non-const. No matter how good the original objective
was, there was always at least one reason not to use const members.
(swap, storing it in a container, etc.)

Only value type objects generally offer those operations. Most objects
aren't value type objects.
Whereas in Java, 80% of the case, I would want "final" for my instance
variables.

It makes me think that is "const member variable" ever useful in C++?

Maybe because of the value semantics of C++ objects, immutable
programming is just not good for C++.

static const is useful, const methods are useful, const parameters are
useful, const T* is useful, but just cannot find niches for const
member variables.

So, what would you use const instance member variable for? Do you use
it at all?

Use it in business logic objects with immutable, per-instance values
that can be set in the initializer list.

Tom
 
R

ralpe

This is similar to the stuff I normally start with. It looks innocent
to have "const member" here. However, later, you will find it hard to
store in a vector or an array. Users may complain it is hard to
aggregate your BankAccount object into their own objects when they do
want to change the bankaccount attribute.
In short, this BankAccount is only good for use as a stack object,
nothing else. And very rarely you will feel satisfied with that.

Again, it is the value semantics that kills the attempt to be
immutable.

Why would you want two BankAccount objects with the same account number (id)?

You should distinguish between values and entities.
Bank accounts should be non-copyable entities:

class BankAccount
{
public:

const int id;

BankAccount(int id) : id(id) {}

private:

BankAccount(BankAccount&); // not implemented
BankAccount operator=(BankAccount&); // not implemented
};

Use (smart) pointers instead of values:
 
R

red floyd

Peter said:
Why not make those static const members?

FWIW I share the observations made by the OP ("static const is useful,
const methods are useful, const parameters are useful, const T* is useful,
but just cannot find niches for const member variables").

I used to use const data members, but it wound up making the assignment
operator a nightmare.
 
B

Ben

Could you please elaborate on how putting into into a container class could
complicate things? I've seen simple container classes before and all they do
is store a load of pointers to seperate objects. How will this intefer with
a const data member?!

-JKop

vector::push_back requires operator= to compile.


I believe some other template libs need some way to do "init - assign"
pattern as well rather than just raii it somewhere and never change it
again. (list, as an exception, does not require changing the object
once constructed, that is because, of course, list is using reference
semantics)
 
B

Ben

Use (smart) pointers instead of values:
boost::shared_ptr<BankAccount>

So, this is to justify the use of const with reference semantics,
which is still consistent with my original observation: value
semantics kills it.

I won't argue about whether value semantics is wanted more often or
less often than reference semantics.

When designing classes, I'm quite reluctant in teaching my users: "you
should use it in this way, not the other way", unless that can
dramatically ease my programming or simplify the architecture.
Unfortunately, const member is never found justifiable with this
criteria.


My intention is to make my class as orthogonal to the language as
possible. that is, users choose how they want to use it, I just define
what my class does and what it requires. If users can use "int" in
certain way, I hope they can use my class the same way as they prefer.

i.e., they should be able to choose where to store this object, in
stack, in heap, embedded in another object, used with smart pointer,
scope guard, blah blah blah, any way they like.

I consider that flexibility very important.
 
D

Denis Remezov

Ben said:
For many times, I've found myself changing my member variables from
const back to non-const. No matter how good the original objective
was, there was always at least one reason not to use const members.
(swap, storing it in a container, etc.)
Whereas in Java, 80% of the case, I would want "final" for my instance
variables.

It makes me think that is "const member variable" ever useful in C++?

Maybe because of the value semantics of C++ objects, immutable
programming is just not good for C++.

static const is useful, const methods are useful, const parameters are
useful, const T* is useful, but just cannot find niches for const
member variables.

So, what would you use const instance member variable for? Do you use
it at all?

Off hand, I recall using it in the following pattern (an example
illustration):

class DataThing {
int get_data(int idx);

public:
//Proxy is not default- or copy-constructible
class Proxy {
DataThing& data_; //would be const if it wasn't for the ref.
int const base_idx_;

public:
Proxy(DataThing& data, int base_idx) : data_(data),
base_idx_(base_idx) {}
int get_data(int idx) {
return data_.get(base_idx_ + idx);
}
};

Proxy getAccessProxy(/*params*/) {
int base_idx;// = function of params
return Proxy(*this, base_idx);
}
//...
};

Denis
 
E

E. Robert Tisdale

Ben said:
For many times, I've found myself changing my member variables
from const back to non-const.

A const variable is an oxymoron.
An object is either a constant or a variable -- not both.
No matter how good the original objective was,
there was always at least one reason not to use const members.

I hope that they were *good* reasons.
(swap, storing it in a container, etc.) Whereas in Java,
80% of the case, I would want "final" for my instance variables.

It makes me think that is "const member variable" ever useful in C++?
Yes.


Maybe because of the value semantics of C++ objects,
immutable programming is just not good for C++.
No.


static const is useful, const methods are useful,
const parameters are useful, const T* is useful,
but just cannot find niches for const member variables.

So, what would you use const instance member variable for?
Do you use it at all?

I do.
Whether private data members are const or not
is important only to the class library developer.
You should begin your class design by making all data members const
then change them to variables
only after you find a good reason for doing so.
It shouldn't surprise you that many data members must be variables
if the object itself must be a variable sometimes.
But even some variable objects will have members that
*should not change* once the object has been constructed.
It is important to qualify them as const
so that other programmers who must maintain your code
will get a diagnostic from the compiler
if they attempt to include code which modifies const data members.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,170
Messages
2,570,925
Members
47,468
Latest member
Fannie44U3

Latest Threads

Top