By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,423 Members | 2,466 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,423 IT Pros & Developers. It's quick & easy.

Non-member vs. Member

P: n/a
Dear all,

Is there a clear distinction how to decide which functions to be
members of a class and which not

How is your attitude (Your general way from your experiences ...)

"If the function changes the state of the object, it ought to be a
member of that object." Reference Accelerated C++, A. Koenig, page 159.

Thx to you all.

Apr 17 '06 #1
Share this Question
Share on Google+
39 Replies


P: n/a
"utab" <um********@gmail.com> wrote in message
news:11**********************@i39g2000cwa.googlegr oups.com...
"If the function changes the state of the object, it ought to be a
member of that object." Reference Accelerated C++, A. Koenig, page 159.


Please note that "ought to be" is less strong than "should always be." It
means "make it a member unless you have a good reason to do otherwise."

One such reason might be a function that changes the state of two or more
objects of different classes. Such a function cannot possibly be members of
both objects. Moreover, such functions are not uncommon: operator>> is
probably the most widely used example.

So sometimes it's impossible to make state-changing functions members of
their objects. Still, it's nice to do so when there is a choice.
Apr 17 '06 #2

P: n/a

utab wrote:
Dear all,

Is there a clear distinction how to decide which functions to be
members of a class and which not
This isn't a C++ question....
How is your attitude (Your general way from your experiences ...)

"If the function changes the state of the object, it ought to be a
member of that object." Reference Accelerated C++, A. Koenig, page 159.


I'm sure there are examples where this doesn't make since, but in
general I agree.

Apr 17 '06 #3

P: n/a
In article <Me******************@bgtnsc04-news.ops.worldnet.att.net>,
"Andrew Koenig" <ar*@acm.org> wrote:
"utab" <um********@gmail.com> wrote in message
news:11**********************@i39g2000cwa.googlegr oups.com...
"If the function changes the state of the object, it ought to be a
member of that object." Reference Accelerated C++, A. Koenig, page 159.


Please note that "ought to be" is less strong than "should always be." It
means "make it a member unless you have a good reason to do otherwise."

One such reason might be a function that changes the state of two or more
objects of different classes. Such a function cannot possibly be members of
both objects. Moreover, such functions are not uncommon: operator>> is
probably the most widely used example.

So sometimes it's impossible to make state-changing functions members of
their objects. Still, it's nice to do so when there is a choice.


I would go so far as to say that if the function changes the state of
two or more objects, it should not be in the class, even if both/all
objects are of the same type.

--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Apr 17 '06 #4

P: n/a
BigBrian wrote:
Is there a clear distinction how to decide which functions to be
members of a class and which not


This isn't a C++ question....


Mr. Manners reminds the Gentle Poster that replies should be on topic if
possible.

For example, C++ brings many special considerations to the question of
whether a function should be semantically a member of an object's
interface, or syntactically a member of its class. operator<<, as already
mention, is semantically a member of both the interfaces of your object and
of ostream. But it is syntactically not a member of your class's methods.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Apr 17 '06 #5

P: n/a
Daniel T. wrote:
In article <Me******************@bgtnsc04-news.ops.worldnet.att.net>,
"Andrew Koenig" <ar*@acm.org> wrote:
"utab" <um********@gmail.com> wrote in message
news:11**********************@i39g2000cwa.googlegr oups.com...
"If the function changes the state of the object, it ought to be a
member of that object." Reference Accelerated C++, A. Koenig, page
159.


Please note that "ought to be" is less strong than "should always
be." It means "make it a member unless you have a good reason to do
otherwise."

One such reason might be a function that changes the state of two or
more objects of different classes. Such a function cannot possibly
be members of both objects. Moreover, such functions are not
uncommon: operator>> is probably the most widely used example.

So sometimes it's impossible to make state-changing functions
members of their objects. Still, it's nice to do so when there is a
choice.


I would go so far as to say that if the function changes the state of
two or more objects, it should not be in the class, even if both/all
objects are of the same type.


Actually, I strongly disagree. If it only concerns this particular type,
then the function _should_ be in the class. It should probably be static
of course.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Apr 17 '06 #6

P: n/a

"utab" <um********@gmail.com> wrote in message
news:11**********************@i39g2000cwa.googlegr oups.com...
Dear all,

Is there a clear distinction how to decide which functions to be
members of a class and which not

How is your attitude (Your general way from your experiences ...)

"If the function changes the state of the object, it ought to be a
member of that object." Reference Accelerated C++, A. Koenig, page 159.

Thx to you all.


Koenig's quote notwithstanding, there is an undesirable aspect of member
functions: they can depend on the implementation. This is sometimes called
"breaking encapsulation". This tends to reduce the maintainability of the
code because if the implementation changes there is more to do and more
mistakes to make. Consider:

void
SomeClass::notify_and_print()
{
notify(); // member function
print(); // another member function;
}

Classes like this which can be written entirely in terms of the rest of an
object's interface can be refactored out:

void
notify_and_print(SomeClass &c)
{
c.notify();
c.print();
}

Although both of these functions will continue to work if the implementation
changes, in the second case I KNOW this to be the case because the second
function has no access to the private parts of SomeClass (i.e. doesn't
"break encapsulation").

As a result of these considerations I usually don't allow member functions
which feature gratuitious access to the implementation. However, I certainly
make exceptions if the interface design seems to call for it.

Cy
Apr 17 '06 #7

P: n/a
In article <e2**********@news.datemas.de>,
"Victor Bazarov" <v.********@comAcast.net> wrote:
Daniel T. wrote:
In article <Me******************@bgtnsc04-news.ops.worldnet.att.net>,
"Andrew Koenig" <ar*@acm.org> wrote:
"utab" <um********@gmail.com> wrote in message
news:11**********************@i39g2000cwa.googlegr oups.com...

"If the function changes the state of the object, it ought to be a
member of that object." Reference Accelerated C++, A. Koenig, page
159.

Please note that "ought to be" is less strong than "should always
be." It means "make it a member unless you have a good reason to do
otherwise."

One such reason might be a function that changes the state of two or
more objects of different classes. Such a function cannot possibly
be members of both objects. Moreover, such functions are not
uncommon: operator>> is probably the most widely used example.

So sometimes it's impossible to make state-changing functions
members of their objects. Still, it's nice to do so when there is a
choice.


I would go so far as to say that if the function changes the state of
two or more objects, it should not be in the class, even if both/all
objects are of the same type.


Actually, I strongly disagree. If it only concerns this particular type,
then the function _should_ be in the class. It should probably be static
of course.


There are readability/writability factors involved. If the function is a
static class member, then it helps scope the function, although the
parameters do that so humm... why should it be static in the class?

As an example:

class Object {
public:
// whatever
};

// returns true if 'a' and 'b' have intersecting areas.
bool hit( Object& a, Object& b );

Why exactly _should_ 'hit' be a static in Object?
--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Apr 17 '06 #8

P: n/a
Daniel T. wrote:
In article <e2**********@news.datemas.de>,
"Victor Bazarov" <v.********@comAcast.net> wrote:
Daniel T. wrote:
In article
<Me******************@bgtnsc04-news.ops.worldnet.att.net>, "Andrew
Koenig" <ar*@acm.org> wrote:

"utab" <um********@gmail.com> wrote in message
news:11**********************@i39g2000cwa.googlegr oups.com...

> "If the function changes the state of the object, it ought to be a
> member of that object." Reference Accelerated C++, A. Koenig, page
> 159.

Please note that "ought to be" is less strong than "should always
be." It means "make it a member unless you have a good reason to
do otherwise."

One such reason might be a function that changes the state of two
or more objects of different classes. Such a function cannot
possibly be members of both objects. Moreover, such functions are
not uncommon: operator>> is probably the most widely used example.

So sometimes it's impossible to make state-changing functions
members of their objects. Still, it's nice to do so when there is
a choice.

I would go so far as to say that if the function changes the state
of two or more objects, it should not be in the class, even if
both/all objects are of the same type.


Actually, I strongly disagree. If it only concerns this particular
type, then the function _should_ be in the class. It should
probably be static of course.


There are readability/writability factors involved. If the function
is a static class member, then it helps scope the function, although
the parameters do that so humm... why should it be static in the
class?

As an example:

class Object {
public:
// whatever
};

// returns true if 'a' and 'b' have intersecting areas.
bool hit( Object& a, Object& b );

Why exactly _should_ 'hit' be a static in Object?


Simply because when I see

hit(a, b);

I really have no idea what 'a' and 'b' are and which of fourteen 'hit'
functions is going to be used. If I see

Object::hit(a, b)

there is no doubt which function is used.

Another argument: limiting the name scope is impossible with arguments.
And limiting the scope of every name is what we should be doing all the
time. Polluting namespace scope with functions that do something very
specific to objects of a single class is... well, polluting.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Apr 17 '06 #9

P: n/a
In article <e2**********@news.datemas.de>,
"Victor Bazarov" <v.********@comAcast.net> wrote:
Daniel T. wrote:
In article <e2**********@news.datemas.de>,
"Victor Bazarov" <v.********@comAcast.net> wrote:
Daniel T. wrote:
In article
<Me******************@bgtnsc04-news.ops.worldnet.att.net>, "Andrew
Koenig" <ar*@acm.org> wrote:

> "utab" <um********@gmail.com> wrote in message
> news:11**********************@i39g2000cwa.googlegr oups.com...
>
>> "If the function changes the state of the object, it ought to be a
>> member of that object." Reference Accelerated C++, A. Koenig, page
>> 159.
>
> Please note that "ought to be" is less strong than "should always
> be." It means "make it a member unless you have a good reason to
> do otherwise."
>
> One such reason might be a function that changes the state of two
> or more objects of different classes. Such a function cannot
> possibly be members of both objects. Moreover, such functions are
> not uncommon: operator>> is probably the most widely used example.
>
> So sometimes it's impossible to make state-changing functions
> members of their objects. Still, it's nice to do so when there is
> a choice.

I would go so far as to say that if the function changes the state
of two or more objects, it should not be in the class, even if
both/all objects are of the same type.

Actually, I strongly disagree. If it only concerns this particular
type, then the function _should_ be in the class. It should
probably be static of course.
There are readability/writability factors involved. If the function
is a static class member, then it helps scope the function, although
the parameters do that so humm... why should it be static in the
class?

As an example:

class Object {
public:
// whatever
};

// returns true if 'a' and 'b' have intersecting areas.
bool hit( Object& a, Object& b );

Why exactly _should_ 'hit' be a static in Object?


Simply because when I see

hit(a, b);

I really have no idea what 'a' and 'b' are and which of fourteen 'hit'
functions is going to be used.


Seems to me that if you don't know what 'a' and 'b' are, you really
shouldn't be writing the code.

If I see

Object::hit(a, b)

there is no doubt which function is used.
The above is nothing more than a compiler enforced version of hungarian
notation.

Another argument: limiting the name scope is impossible with arguments.
And limiting the scope of every name is what we should be doing all the
time. Polluting namespace scope with functions that do something very
specific to objects of a single class is... well, polluting.


Unless, of course, the namespace is for "things that work with Objects"
presumably...
--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Apr 17 '06 #10

P: n/a
I V
Cy Edmunds wrote:
As a result of these considerations I usually don't allow member functions
which feature gratuitious access to the implementation. However, I certainly


This has the disadvantage that the way in which the function is called
depends on whether or not it needs to access the implementation, i.e.

o.needs_acess();

vs,

doesnt_need_access(o);

This kind of breaks encapsulation too, as the interface of the class
depends on implementation details, namely, whether or not a particular
function requires access to the internals of the class. To get round
this, I've sometimes considered writing classes with no public member
functions at all. I've never actually written a whole program like
this, because it's sufficiently odd that it might constitute a
stumbling block for anyone else reading the code, but I'd be interested
in what others think of the idea. E.g:

class MyClass
{
private:
SomeClass data_;

virtual void do_operation();
friend void needs_access();
public:
explicit MyClass(SomeClass& d)
: data_(d)
{ }

virtual ~MyClass();
};

void needs_access(MyClass& c)
{
...
}

void doesnt_need_access(MyClass& c)
{
...
}

void do_operation(MyClass& c)
{
c.do_operation();
}

Apr 17 '06 #11

P: n/a

"I V" <wr******@gmail.com> wrote in message
news:11**********************@e56g2000cwe.googlegr oups.com...
Cy Edmunds wrote:
As a result of these considerations I usually don't allow member
functions
which feature gratuitious access to the implementation. However, I
certainly
This has the disadvantage that the way in which the function is called
depends on whether or not it needs to access the implementation, i.e.

o.needs_acess();

vs,

doesnt_need_access(o);


This is true but sort of unavoidable. Sooner or later you will want to get
some sort of extended functionality and you only have two choices: derive a
new class with the member function you want, or just write another function:

didnt_think_of_this_at_first(o);

Deriving a new class just to get a new function is often a poor idea for a
lot of reasons. For example:

my_string : public std::string
{
public:
void my_leet_function();
};

Yech.

This kind of breaks encapsulation too, as the interface of the class
depends on implementation details, namely, whether or not a particular
function requires access to the internals of the class.
This is certainly not what I would call breaking encapsulation. Actually I
don't see the problem here at all.

To get round this, I've sometimes considered writing classes with no public member
functions at all. I've never actually written a whole program like
this, because it's sufficiently odd that it might constitute a
stumbling block for anyone else reading the code, but I'd be interested
in what others think of the idea. E.g:

class MyClass
{
private:
SomeClass data_;

virtual void do_operation();
friend void needs_access();
public:
explicit MyClass(SomeClass& d)
: data_(d)
{ }

virtual ~MyClass();
};

void needs_access(MyClass& c)
{
...
}

void doesnt_need_access(MyClass& c)
{
...
}

void do_operation(MyClass& c)
{
c.do_operation();
}


I think it would be a stumbling block for anyone else reading the code!
Also, if you have some reason to try to hide which things need access to the
internals and which things don't, this is hardly a solution.

Cy
Apr 17 '06 #12

P: n/a

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:e2**********@news.datemas.de...
Daniel T. wrote:
In article <e2**********@news.datemas.de>,
"Victor Bazarov" <v.********@comAcast.net> wrote:
Daniel T. wrote:
In article
<Me******************@bgtnsc04-news.ops.worldnet.att.net>, "Andrew
Koenig" <ar*@acm.org> wrote:

> "utab" <um********@gmail.com> wrote in message
> news:11**********************@i39g2000cwa.googlegr oups.com...
>
>> "If the function changes the state of the object, it ought to be a
>> member of that object." Reference Accelerated C++, A. Koenig, page
>> 159.
>
> Please note that "ought to be" is less strong than "should always
> be." It means "make it a member unless you have a good reason to
> do otherwise."
>
> One such reason might be a function that changes the state of two
> or more objects of different classes. Such a function cannot
> possibly be members of both objects. Moreover, such functions are
> not uncommon: operator>> is probably the most widely used example.
>
> So sometimes it's impossible to make state-changing functions
> members of their objects. Still, it's nice to do so when there is
> a choice.

I would go so far as to say that if the function changes the state
of two or more objects, it should not be in the class, even if
both/all objects are of the same type.

Actually, I strongly disagree. If it only concerns this particular
type, then the function _should_ be in the class. It should
probably be static of course.
There are readability/writability factors involved. If the function
is a static class member, then it helps scope the function, although
the parameters do that so humm... why should it be static in the
class?

As an example:

class Object {
public:
// whatever
};

// returns true if 'a' and 'b' have intersecting areas.
bool hit( Object& a, Object& b );

Why exactly _should_ 'hit' be a static in Object?


Simply because when I see

hit(a, b);

I really have no idea what 'a' and 'b' are and which of fourteen 'hit'
functions is going to be used. If I see

Object::hit(a, b)

there is no doubt which function is used.


I think this argument is a giant stretch but even if I were to buy it what
if you later need some other functionality? You can always write your own

bool miss( Object& a, Object& b );

but you may not be able to add you own static function. That's why I favor
making the interface as simple as possible and using stand alone functions,
overloaded if necessary.

If you really want to insist on qualifiers you can use namespaces:

namespace dubious
{
bool miss( Object& a, Object& b );
}

dubious::miss(a, b);

Kinda dumb, but at least it is extendable.

Another argument: limiting the name scope is impossible with arguments.
And limiting the scope of every name is what we should be doing all the
time. Polluting namespace scope with functions that do something very
specific to objects of a single class is... well, polluting.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

Apr 17 '06 #13

P: n/a
Cy Edmunds wrote:
[...]
If you really want to insist on qualifiers you can use namespaces:

namespace dubious
{
bool miss( Object& a, Object& b );
}

dubious::miss(a, b);

Kinda dumb, but at least it is extendable.


No more and no less than classes. I can always wrap one class in another
to "add functionality" AFA static members are concerned.

Classes are not namespaces and namespaces are not classes. Substituting
one for the other just for the sake of substituting is pointless. Any
functionality specific to a class belongs to the class.

V
--
Please remove capital As from my address when replying by mail
Apr 18 '06 #14

P: n/a

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:Ne********************@comcast.com...
Cy Edmunds wrote:
[...]
If you really want to insist on qualifiers you can use namespaces:

namespace dubious
{
bool miss( Object& a, Object& b );
}

dubious::miss(a, b);

Kinda dumb, but at least it is extendable.


No more and no less than classes. I can always wrap one class in another
to "add functionality" AFA static members are concerned.

Classes are not namespaces and namespaces are not classes. Substituting
one for the other just for the sake of substituting is pointless. Any
functionality specific to a class belongs to the class.


I agree with everything you said except the last sentence. In C++ there is
no reason to break encapsulation just because you want to add some
functionality.

Cy
Apr 18 '06 #15

P: n/a
Cy Edmunds wrote:
[..] In C++
there is no reason to break encapsulation just because you want to
add some functionality.


I've read that expression several times today, and still have not
understood how putting functionality that specific to any particular
class inside that class means "breaking encapsulation". Care to
elaborate?

V
--
Please remove capital As from my address when replying by mail
Apr 18 '06 #16

P: n/a
In article <11**********************@i39g2000cwa.googlegroups .com>,
"utab" <um********@gmail.com> wrote:
Dear all,

Is there a clear distinction how to decide which functions to be
members of a class and which not

How is your attitude (Your general way from your experiences ...)

"If the function changes the state of the object, it ought to be a
member of that object." Reference Accelerated C++, A. Koenig, page 159.


An important point that I think needs to be mentioned. No
member-function should return with the class invariant broken (however
it can break the invariant inside itself.)

So for example:

class Range {
// invariant: low() < high()
public:
int low() const;
int high() const;
void setLow( int v );
// postcondition: low() == v
};

The 'setLow' member-function above has a real problem, it can't
guarantee it's postcondition and its invariant unless the user of the
class first checks to see if the value passed in is less than 'high()'.

Many new programmers, will ignore this glaring problem, some will add an
assert( v < high() ) or throw and exception if v >= high() and think
they are clever, but neither "solution" really solves the problem. The
user of the class must still do most of the work ensuring the invariant
stays true (and that is supposed to be the class' responsibility.)

There are only two solutions, either 'setLow's precondition needs to
change to something that works [ like: low() == min( v, high() - 1 ) ],
or the function needs to go away.

To generalize this rule. Anytime a member-function *requires* the object
to be in a particular state in order to be called, the member-function
is poorly formed and needs to be fixed or removed.
--
Magic depends on tradition and belief. It does not welcome observation,
nor does it profit by experiment. On the other hand, science is based
on experience; it is open to correction by observation and experiment.
Apr 18 '06 #17

P: n/a
I V
Cy Edmunds wrote:
"I V" <wr******@gmail.com> wrote in message
This has the disadvantage that the way in which the function is called
depends on whether or not it needs to access the implementation, i.e.

o.needs_acess();

vs,

doesnt_need_access(o);


This is true but sort of unavoidable. Sooner or later you will want to get
some sort of extended functionality and you only have two choices: derive a
new class with the member function you want, or just write another function:


Well, that makes me wonder if having a special syntax for calling
member functions is actually a good thing. After all, why should it
matter to the user of the class if the operation on an object is
defined by the class or by some later code? Combining the idea of
"requires access to class internals," "is part of the class's
interface" and "is an operation on objects of the class" into one
syntax is, perhaps, confusing.

I belive in the Dylan language, obj.meth(arg) is just syntactic sugar
for meth(obj, arg) , which strikes me as quite an attractive design (in
Dylan, you define a function which does dynamic dispatch on the types
of its arguments outside of a class definition).
This kind of breaks encapsulation too, as the interface of the class
depends on implementation details, namely, whether or not a particular
function requires access to the internals of the class.


This is certainly not what I would call breaking encapsulation. Actually I
don't see the problem here at all.


Whether a function needs access to the internals of a class depends on
the implementation, no? A maybe interesting example is a class with two
methods, each of which can be implemented in terms of the other; thus,
which you make access the class internals is a matter of choice. If you
make one a member function and one a non-member, you're exposing this
choice in the interface, which sounds like breaking encapsulation to
me. Certainly, if you later decide to change your implementation
(perhaps implementing function A in terms of function B turns out to be
more efficient than the other way round), making one a member and the
other a non-member will cause you problems.

Apr 18 '06 #18

P: n/a
Victor Bazarov wrote:
Cy Edmunds wrote:
[..] In C++
there is no reason to break encapsulation just because you want to
add some functionality.

I've read that expression several times today, and still have not
understood how putting functionality that specific to any particular
class inside that class means "breaking encapsulation". Care to
elaborate?


If you add functionality to a class via (non-friend) non-members, then
that functionality necessarily only depends on the public interface of
the class.

Tom
Apr 18 '06 #19

P: n/a
Tom Widmer wrote:
Victor Bazarov wrote:
Cy Edmunds wrote:
[..] In C++
there is no reason to break encapsulation just because you want to
add some functionality.

I've read that expression several times today, and still have not
understood how putting functionality that specific to any particular
class inside that class means "breaking encapsulation". Care to
elaborate?


If you add functionality to a class via (non-friend) non-members, then
that functionality necessarily only depends on the public interface of
the class.


Yes, and?... Where is the "breaking" part? If the functionality is
instead actually _part_ of public interface, what's broken? Or is adding
to a class' interface in fact "breaking" some fragile "encapsulation"?

What is the essential difference between

class A {
// some interface, public or otherwise
};

void foo(A& a) {
// some implemenation
}

and

class A {
// some interface, public or otherwise
static void foo(A& a) {
// same implemenation as above
}
};

What is broken in the second case compared to the first one?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Apr 18 '06 #20

P: n/a

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:e2**********@news.datemas.de...
Tom Widmer wrote:
Victor Bazarov wrote:
Cy Edmunds wrote:

[..] In C++
there is no reason to break encapsulation just because you want to
add some functionality.
I've read that expression several times today, and still have not
understood how putting functionality that specific to any particular
class inside that class means "breaking encapsulation". Care to
elaborate?


If you add functionality to a class via (non-friend) non-members, then
that functionality necessarily only depends on the public interface of
the class.


Yes, and?... Where is the "breaking" part? If the functionality is
instead actually _part_ of public interface, what's broken? Or is adding
to a class' interface in fact "breaking" some fragile "encapsulation"?

What is the essential difference between

class A {
// some interface, public or otherwise
};

void foo(A& a) {
// some implemenation
}

and

class A {
// some interface, public or otherwise
static void foo(A& a) {
// same implemenation as above
}
};

What is broken in the second case compared to the first one?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


In the second case a mistake in the implementation of foo can result in
violation of invariants of the class.
Apr 18 '06 #21

P: n/a
Cy Edmunds wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:e2**********@news.datemas.de...
Tom Widmer wrote:
Victor Bazarov wrote:
Cy Edmunds wrote:

> [..] In C++
> there is no reason to break encapsulation just because you want to
> add some functionality.
I've read that expression several times today, and still have not
understood how putting functionality that specific to any
particular class inside that class means "breaking encapsulation".
Care to elaborate?

If you add functionality to a class via (non-friend) non-members,
then that functionality necessarily only depends on the public
interface of the class.


Yes, and?... Where is the "breaking" part? If the functionality is
instead actually _part_ of public interface, what's broken? Or is
adding to a class' interface in fact "breaking" some fragile
"encapsulation"? What is the essential difference between

class A {
// some interface, public or otherwise
};

void foo(A& a) {
// some implemenation
}

and

class A {
// some interface, public or otherwise
static void foo(A& a) {
// same implemenation as above
}
};

What is broken in the second case compared to the first one?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


In the second case a mistake in the implementation of foo can result
in violation of invariants of the class.


Yes, I agree. Is that the whole thing or there's something else?

If that's the whole thing, then in my book the benefits of limiting the
scope of functionality outweigh the benefits of preventing my potential
mistakes while implementing 'foo'. *I* do not make any. The users of
my classes OTOH do. And they make mistakes mostly because of an unclear
intentions, communicated poorly by placing functionality in overly broad
scopes.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Apr 18 '06 #22

P: n/a

"I V" <wr******@gmail.com> wrote in message
news:11**********************@i39g2000cwa.googlegr oups.com...
Cy Edmunds wrote:
"I V" <wr******@gmail.com> wrote in message
> This has the disadvantage that the way in which the function is called
> depends on whether or not it needs to access the implementation, i.e.
>
> o.needs_acess();
>
> vs,
>
> doesnt_need_access(o);
This is true but sort of unavoidable. Sooner or later you will want to
get
some sort of extended functionality and you only have two choices: derive
a
new class with the member function you want, or just write another
function:


Well, that makes me wonder if having a special syntax for calling
member functions is actually a good thing.


You certainly have a good point there. Still, if we are going to program in
C++ we need to deal with it as it actually is.

After all, why should it matter to the user of the class if the operation on an object is
defined by the class or by some later code? Combining the idea of
"requires access to class internals," "is part of the class's
interface" and "is an operation on objects of the class" into one
syntax is, perhaps, confusing.

I belive in the Dylan language, obj.meth(arg) is just syntactic sugar
for meth(obj, arg) , which strikes me as quite an attractive design (in
Dylan, you define a function which does dynamic dispatch on the types
of its arguments outside of a class definition).
> This kind of breaks encapsulation too, as the interface of the class
> depends on implementation details, namely, whether or not a particular
> function requires access to the internals of the class.
This is certainly not what I would call breaking encapsulation. Actually
I
don't see the problem here at all.


Whether a function needs access to the internals of a class depends on
the implementation, no?


No, only the interface. For instance:

class IComplex
{
public:
virtual double re() const = 0;
virtual double im() const = 0;
virtual ~IComplex() {}
};

double mod(IComplex const &c)
{
return c.re()*c.re() + c.im()*c.im();
}

I can tell that mod does not require access to the internals from the
interface alone. Of course I can't tell if IComplex::re() or IComplex::im()
actually require access to any internals (they might just generate random
numbers for instance). We can only say that these functions have access to
the internal representation which makes them dangerous -- in a bad
implementation they might break invariants promised by the class
documentation in a way mod could never do.

A maybe interesting example is a class with two methods, each of which can be implemented in terms of the other; thus,
which you make access the class internals is a matter of choice. If you
make one a member function and one a non-member, you're exposing this
choice in the interface, which sounds like breaking encapsulation to
me. Certainly, if you later decide to change your implementation
(perhaps implementing function A in terms of function B turns out to be
more efficient than the other way round), making one a member and the
other a non-member will cause you problems.

Apr 18 '06 #23

P: n/a
Victor Bazarov wrote:
Tom Widmer wrote:
If you add functionality to a class via (non-friend) non-members, then
that functionality necessarily only depends on the public interface of
the class.

Yes, and?... Where is the "breaking" part? If the functionality is
instead actually _part_ of public interface, what's broken? Or is adding
to a class' interface in fact "breaking" some fragile "encapsulation"?

What is the essential difference between

class A {
// some interface, public or otherwise
};

void foo(A& a) {
// some implemenation
}

and

class A {
// some interface, public or otherwise
static void foo(A& a) {
// same implemenation as above
}
};

What is broken in the second case compared to the first one?


The number of bits of code that need to be checked when the
implementation of A changes.

Tom
Apr 18 '06 #24

P: n/a
Tom Widmer wrote:
Victor Bazarov wrote:
Tom Widmer wrote:
If you add functionality to a class via (non-friend) non-members,
then that functionality necessarily only depends on the public
interface of the class.

Yes, and?... Where is the "breaking" part? If the functionality is
instead actually _part_ of public interface, what's broken? Or is
adding to a class' interface in fact "breaking" some fragile
"encapsulation"? What is the essential difference between

class A {
// some interface, public or otherwise
};

void foo(A& a) {
// some implemenation
}

and

class A {
// some interface, public or otherwise
static void foo(A& a) {
// same implemenation as above
}
};

What is broken in the second case compared to the first one?


The number of bits of code that need to be checked when the
implementation of A changes.


Please elaborate. Thanks.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Apr 18 '06 #25

P: n/a
In article <e2**********@news.datemas.de>,
"Victor Bazarov" <v.********@comAcast.net> wrote:
Cy Edmunds wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message

class A {
// some interface, public or otherwise
};

void foo(A& a) {
// some implemenation
}

and

class A {
// some interface, public or otherwise
static void foo(A& a) {
// same implemenation as above
}
};

What is broken in the second case compared to the first one?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


In the second case a mistake in the implementation of foo can result
in violation of invariants of the class.


Yes, I agree. Is that the whole thing or there's something else?

If that's the whole thing, then in my book the benefits of limiting the
scope of functionality outweigh the benefits of preventing my potential
mistakes while implementing 'foo'. *I* do not make any. The users of
my classes OTOH do. And they make mistakes mostly because of an unclear
intentions, communicated poorly by placing functionality in overly broad
scopes.


How exactly have you changed the scope of foo by putting it in the class
rather than in out of it? I missed that part. Seems to me that in both
examples, the scope of foo is the same, only the name has changed.
Apr 18 '06 #26

P: n/a
Daniel T. wrote:
[..] Seems to me [..]


Sorry, I'm bailing out. I got bored by this nonsense.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Apr 18 '06 #27

P: n/a
In article <e2**********@news.datemas.de>,
"Victor Bazarov" <v.********@comAcast.net> wrote:
Daniel T. wrote:
[..] Seems to me [..]


Sorry, I'm bailing out. I got bored by this nonsense.


I'm not saying your wrong Victor, I'm just trying to figure out why you
are so sure you are right...

Please, explain to me how making a function a public static member of a
class gives it a smaller scope than one that is free standing.
Apr 18 '06 #28

P: n/a
Daniel T. wrote:
In article <e2**********@news.datemas.de>,
"Victor Bazarov" <v.********@comAcast.net> wrote:
Daniel T. wrote:
[..] Seems to me [..]


Sorry, I'm bailing out. I got bored by this nonsense.


I'm not saying your wrong Victor, I'm just trying to figure out why
you are so sure you are right...

Please, explain to me how making a function a public static member of
a class gives it a smaller scope than one that is free standing.


I don't understand the question, probably. The scope of a member function
is the class of which it's the member. That's smaller than the enclosing
[namespace or other type] scope. I thought that was obvious.

Anyway, I am marking this thread "ignore". Trick me into participating in
a thread from which I bailed out, shame on you. Trick me twice...

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Apr 18 '06 #29

P: n/a

"utab" <um********@gmail.com> wrote in message
news:11**********************@i39g2000cwa.googlegr oups.com...
Dear all,

Is there a clear distinction how to decide which functions to be
members of a class and which not

How is your attitude (Your general way from your experiences ...)

"If the function changes the state of the object, it ought to be a
member of that object." Reference Accelerated C++, A. Koenig, page 159.

Thx to you all.


Here is what Scott Meyers has to say:

http://www.ddj.com/dept/cpp/184401197
Apr 19 '06 #30

P: n/a
Victor Bazarov wrote:
Tom Widmer wrote:

class A {
// some interface, public or otherwise
};

void foo(A& a) {
// some implemenation
}

and

class A {
// some interface, public or otherwise
static void foo(A& a) {
// same implemenation as above
}
};

What is broken in the second case compared to the first one?


The number of bits of code that need to be checked when the
implementation of A changes.

Please elaborate. Thanks.


Specifically, foo needs to be checked only in case 2 if the
implementation of A later changes. In case 1, the amount of code that
may depend on the implementation of A (and must be examined to determine
this) is less.

Tom
Apr 19 '06 #31

P: n/a
In article <e2**********@news.datemas.de>,
"Victor Bazarov" <v.********@comAcast.net> wrote:
The scope of a member function
is the class of which it's the member. That's smaller than the enclosing
[namespace or other type] scope. I thought that was obvious.


I thought the "scope" of a variable or function had something to do with
where it can be used in the program. Am I wrong?

In the following code:

class Foo {
public:
static int bar();
};

int bar();

does "Foo::bar()" have a smaller scope than "bar()" or not? If it does,
what does "scope" mean?

Victor says that Foo::bar() has a smaller scope and I tend to respect
his opinion (if not his somewhat abrasive demeanor.)
Apr 19 '06 #32

P: n/a
Daniel T. wrote:
In article <e2**********@news.datemas.de>,
"Victor Bazarov" <v.********@comAcast.net> wrote:

The scope of a member function
is the class of which it's the member. That's smaller than the enclosing
[namespace or other type] scope. I thought that was obvious.

I thought the "scope" of a variable or function had something to do with
where it can be used in the program. Am I wrong?


Yes.

In the following code:

class Foo {
public:
static int bar();
};

int bar();

does "Foo::bar()" have a smaller scope than "bar()" or not? If it does,
what does "scope" mean?
The scope is the declarative region of the program in which the name (in
unqualified form, importantly) is valid.
Victor says that Foo::bar() has a smaller scope and I tend to respect
his opinion (if not his somewhat abrasive demeanor.)


Victor is right here, but his abrasive demeanor is often used to
disguise ignorance or mistakes. He's not reading anyway apparently. ;)

In this case he appears to want to put the function into class scope to
avoid name clashes. However, an alternative (and more flexible) way of
doing this is to use namespaces.

Tom
Apr 19 '06 #33

P: n/a
Daniel T. wrote:
In the following code:

class Foo {
public:
static int bar();
};

int bar();

does "Foo::bar()" have a smaller scope than "bar()" or not? If it does,
what does "scope" mean?

Victor says that Foo::bar() has a smaller scope and I tend to respect
his opinion (if not his somewhat abrasive demeanor.)


If one scope is contained entirely within another, then it can be said
to be smaller. For other cases, you need to develop some notion of
scope size. Even if there is containment, you could argue that any
shadowed pieces of the outer scope do not contribute to its size, thus
casting doubt on the validity of using containment to determine
relative size.

The scope of the name of the non-member function bar extends from its
point of declaration to the end of the translation unit. (That scope
may be interrupted in places by shadowing definitions of bar).

The scope of Foo::bar() is the class scope of Foo. Within a translation
unit, that scope is the class definition, and also the bodies of any
subsequent member function definitions.

In the above example, the Foo class declaration is placed in a region
of program text where the file scope bar() isn't visible yet. The two
scopes do not overlap, and we cannot say which is larger.

Apr 19 '06 #34

P: n/a

Tom Widmer wrote:
In this case he appears to want to put the function into class scope to
avoid name clashes. However, an alternative (and more flexible) way of
doing this is to use namespaces.


Is it in fact true that an alternative is namespaces? I think Victor's
point was that putting it in a class makes it so it can't be
automatically resolved. I am not completely sure when and where
functions can be pulled out of namespace scope into the current scope
but I do know there are cases when this can occur (One of the red books
explains in some detail). I don't believe this can happen if the
function is a static class member.

Apr 19 '06 #35

P: n/a
Noah Roberts wrote:
Tom Widmer wrote:

In this case he appears to want to put the function into class scope to
avoid name clashes. However, an alternative (and more flexible) way of
doing this is to use namespaces.

Is it in fact true that an alternative is namespaces? I think Victor's
point was that putting it in a class makes it so it can't be
automatically resolved. I am not completely sure when and where
functions can be pulled out of namespace scope into the current scope
but I do know there are cases when this can occur (One of the red books
explains in some detail). I don't believe this can happen if the
function is a static class member.


Yes, ADL allows unqualified names from other namespaces to be considered
in function calls. But you can qualify function calls to prevent this.
Quite a common practice is to use quite small namespaces (in contrast to
the monolithic namespace std), that only contain a class and its related
functions.

Anyway, I disagree with Victor on this. If one adds every little
function as an extra static member of a class, one ends up with reams of
code that need to be checked and possibly changed when you change the
implementation. Imagine, for example, a string class. Imagine that you
have lots of utility string operations, and these are all static (and
non-static) members of the string class (since they operate on strings,
that's where Victor things they should be). Now think about the job
involved in changing the string class to use reference counting, or SSO
- which of those utility methods needs changing? Some? All? You have to
check each of them in any case - this could mean checking and possibly
reimplementing 50 utility functions. Compare to the alternative, where
the string interface is minimal and complete, and the utility functions
are separate, namespace scope, non-friend functions. None of them needs
to be modified for the change of implementation.

Tom
Apr 20 '06 #36

P: n/a

Tom Widmer wrote:
Noah Roberts wrote:
Tom Widmer wrote:

In this case he appears to want to put the function into class scope to
avoid name clashes. However, an alternative (and more flexible) way of
doing this is to use namespaces.

Is it in fact true that an alternative is namespaces? I think Victor's
point was that putting it in a class makes it so it can't be
automatically resolved. I am not completely sure when and where
functions can be pulled out of namespace scope into the current scope
but I do know there are cases when this can occur (One of the red books
explains in some detail). I don't believe this can happen if the
function is a static class member.


Yes, ADL allows unqualified names from other namespaces to be considered
in function calls. But you can qualify function calls to prevent this.
Quite a common practice is to use quite small namespaces (in contrast to
the monolithic namespace std), that only contain a class and its related
functions.


Here is an example of ADL pulling in unqualified names from namespaces
so namespace scope is quite vulnerable if not coded carefully,

namespace n1{
struct S {};
void foo(S) {}
}
void bar(){
n1::S s;
foo(s);
}

Apr 20 '06 #37

P: n/a
In article <e2**********@emma.aioe.org>,
Tom Widmer <to********@hotmail.com> wrote:
Daniel T. wrote:
In article <e2**********@news.datemas.de>,
"Victor Bazarov" <v.********@comAcast.net> wrote:

The scope of a member function
is the class of which it's the member. That's smaller than the enclosing
[namespace or other type] scope. I thought that was obvious.

I thought the "scope" of a variable or function had something to do with
where it can be used in the program. Am I wrong?


Yes.

In the following code:

class Foo {
public:
static int bar();
};

int bar();

does "Foo::bar()" have a smaller scope than "bar()" or not? If it does,
what does "scope" mean?


The scope is the declarative region of the program in which the name (in
unqualified form, importantly) is valid.


Thank you for the explanation. Previously, I was of the opinion that
visibility defined scope, and the only thing that making 'func()' a
public static member (or a member of a namespace for that matter) got
you was a mangled name so it was less likely to be called in incorrect
contexts.

Hopefully, I will not confuse scope and visibility again. :-)
Apr 20 '06 #38

P: n/a

Daniel T. wrote:
In article <e2**********@emma.aioe.org>,
Tom Widmer <to********@hotmail.com> wrote:
Daniel T. wrote:
In article <e2**********@news.datemas.de>,
"Victor Bazarov" <v.********@comAcast.net> wrote:
>The scope of a member function
>is the class of which it's the member. That's smaller than the enclosing
>[namespace or other type] scope. I thought that was obvious.
I thought the "scope" of a variable or function had something to do with
where it can be used in the program. Am I wrong?


Yes.

In the following code:

class Foo {
public:
static int bar();
};

int bar();

does "Foo::bar()" have a smaller scope than "bar()" or not? If it does,
what does "scope" mean?


The scope is the declarative region of the program in which the name (in
unqualified form, importantly) is valid.


Thank you for the explanation. Previously, I was of the opinion that
visibility defined scope, and the only thing that making 'func()' a
public static member (or a member of a namespace for that matter) got
you was a mangled name so it was less likely to be called in incorrect
contexts.

Hopefully, I will not confuse scope and visibility again. :-)


If I understand correctly, names in one scope may or may not be visible
in another scope. The rules that define visibility crosses but not
coincide with rules that define scoping.

Apr 21 '06 #39

P: n/a

utab wrote:
Dear all,

Is there a clear distinction how to decide which functions to be
members of a class and which not

How is your attitude (Your general way from your experiences ...)

"If the function changes the state of the object, it ought to be a
member of that object." Reference Accelerated C++, A. Koenig, page 159.


Having a small, sensible, significant set of member functions. Other
functions should be non-member.
I like to think that the public interface, as defined in the class
definition, is the "mathematical definition of the object class".

Member functions have access to internal details of the class.
The encapsulation is here, in order to have the smallest number of
functions accessing a particular implementation detail.

I think that these two Herb Sutter's articles are revelant here:
http://www.gotw.ca/publications/mill02.htm
http://www.gotw.ca/gotw/084.htm

Apr 25 '06 #40

This discussion thread is closed

Replies have been disabled for this discussion.