Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

OOP is the new GOTO

332 views
Skip to first unread message

fir

unread,
Jun 1, 2018, 10:56:52 AM6/1/18
to
to make things somewhat clear ;c and make a bit of foam... i think 'Object Oriented Programming' when you sue it - making objects passing pointers (and yet more unfortunate biuldking more comple trashy patterns - is the new goto... ooop considered harmfull , dont use it as you dont use big gotos

Mr Flibble

unread,
Jun 1, 2018, 1:32:08 PM6/1/18
to
On 01/06/2018 15:56, fir wrote:
> to make things somewhat clear ;c and make a bit of foam... i think 'Object Oriented Programming' when you sue it - making objects passing pointers (and yet more unfortunate biuldking more comple trashy patterns - is the new goto... ooop considered harmfull , dont use it as you dont use big gotos

I wrote an article on a related matter (Law of Demeter) a decade ago:

http://i42.co.uk/stuff/spaghetti.htm

The Perils of Object Oriented Spaghetti (or Law of Demeter and Singletons)
Law of Demeter or Principle of Least Knowledge is a simple design style
for developing software that purportedly results in a lower coupling
between elements of a computer program. Lower coupling is beneficial as
it results in code which is easier to maintain and understand.

It is the opinion of this programmer however that the Law of Demeter is in
fact a load of old toot (rubbish) as it advocates invoking methods on
global objects: this is in contradiction to a "Principle of Least
Knowledge". "For pragmatic reasons" are weasel words. Global variables
(non-constants) are bad, period.
On a related matter singletons are an anti-pattern as well as a pattern;
use rarely not routinely. Singletons are little more than disguised
global variables and do themselves violate a principle of least knowledge
resulting in tighter coupling/hidden dependencies (or object oriented
"spaghetti" code) as well as being problematic for multi-threaded designs.

Of course it is not always possible to avoid singletons; one example is
when you have an external entry point into your program other than main
(e.g. a C callback function in a DLL) that doesn't provide context
information via a parameter.

____━━____┓━╭━━━━━━╮
____━━____┗┓|::::::::^━━━━^
____━━____━┗|:::::::::|。◕‿‿ ◕。|
____━━____━━╰O--O-O--O ╯
18 Dec 2009

/Flibble

--
"Suppose it’s all true, and you walk up to the pearly gates, and are
confronted by God," Bryne asked on his show The Meaning of Life. "What
will Stephen Fry say to him, her, or it?"
"I’d say, bone cancer in children? What’s that about?" Fry replied.
"How dare you? How dare you create a world to which there is such misery
that is not our fault. It’s not right, it’s utterly, utterly evil."
"Why should I respect a capricious, mean-minded, stupid God who creates a
world that is so full of injustice and pain. That’s what I would say."

Siri Cruise

unread,
Jun 1, 2018, 2:35:56 PM6/1/18
to
In article <b00eee21-8cb3-4bfb...@googlegroups.com>,
A finite state machine is most succintly expressed with states as labels and
transitions as gotos. Give the states comprehensible names and write the states
in a consistent notation, and it will be as comprehensible as aught else.

The controversy arose because Fortran at that time had very few single-entry
single-exit control structures, so it required particular good discipline and
comments to allow the code modularisation and isolation needed to understand
programmes. Even with single-entry/exit code, you can encode the mess into
variables instead of labels that then have be tracked all over the place. And
now you encode the mess into objects.

Good programming then as now requires writing isolateable code with contractual
interfaces that make explicit what is done, in abstract, and make the control
and data transfers explicit. Then the software can be decomposed into small
chunks our monkey brains can cope with.

You can code in Fortran 66 no matter what language you use. (I need to finish my
object oriented Fortran 77 (OOF) compiler.)

--
:-<> Siri Seal of Disavowal #000-001. Disavowed. Denied. Deleted. @
'I desire mercy, not sacrifice.' /|\
I'm saving up to buy the Donald a blue stone This post / \
from Metebelis 3. All praise the Great Don! insults Islam. Mohammed

bart...@gmail.com

unread,
Jun 1, 2018, 3:53:57 PM6/1/18
to
On Friday, 1 June 2018 19:35:56 UTC+1, Siri Cruise wrote:

> You can code in Fortran 66 no matter what language you use.


Not in Python. Or any language that has decided it knows best and has got rid of 'goto', even though it's one of the simplest features to implement.

There are numerous uses, even if it doesn't belong in quality code, including porting algorithms from other languages that use goto or a control flow statement that doesn't exist in the target language.

--
bart

Siri Cruise

unread,
Jun 1, 2018, 7:11:43 PM6/1/18
to
In article <7af124b6-bcb6-4a97...@googlegroups.com>,
bart...@gmail.com wrote:

> On Friday, 1 June 2018 19:35:56 UTC+1, Siri Cruise wrote:
>
> > You can code in Fortran 66 no matter what language you use.
>
>
> Not in Python. Or any language that has decided it knows best and has got rid
> of 'goto', even though it's one of the simplest features to implement.

With a compiler that optimises away tail recursion, functions become labels, and
applications become gotos.

Juha Nieminen

unread,
Jun 4, 2018, 3:04:31 AM6/4/18
to
fir <profes...@gmail.com> wrote:
> to make things somewhat clear ;c and make a bit of foam...
> i think 'Object Oriented Programming' when you sue it - making
> objects passing pointers

Object-oriented programming doesn't necessitate passing objects by pointer.

Tim Rentsch

unread,
Jun 13, 2018, 9:33:14 PM6/13/18
to
Siri Cruise <chine...@yahoo.com> writes:

> In article <7af124b6-bcb6-4a97...@googlegroups.com>,
> bart...@gmail.com wrote:
>
>> On Friday, 1 June 2018 19:35:56 UTC+1, Siri Cruise wrote:
>>
>>> You can code in Fortran 66 no matter what language you use.
>>
>> Not in Python. Or any language that has decided it knows best and has got rid
>> of 'goto', even though it's one of the simplest features to implement.
>
> With a compiler that optimises away tail recursion, functions become labels, and
> applications become gotos.

But with an important difference - a tail call returns from its
enclosing function right then and there, whereas a goto may
wander in the weeds inside the same function, going who knows
where. A tail call is always a very structured goto.

Tim Rentsch

unread,
Jun 13, 2018, 9:34:23 PM6/13/18
to
I find this statement somewhat laughable. It's no accident
that 'this' is a pointer rather than a value.

Siri Cruise

unread,
Jun 13, 2018, 11:09:54 PM6/13/18
to
In article <kfnmuvy...@x-alumni2.alumni.caltech.edu>,
Write a program with a single while loop and a single case:

int state := 1;
while state>0 do
case state in
1: (first executed basic block; state := n),
...
n: (nth basic block; state := m),
...
r: (final executed basic block: state := 0)
esac
od

Öö Tiib

unread,
Jun 14, 2018, 2:09:32 AM6/14/18
to
Stroustrup did somewhere explain that 'this' is a reference that uses
pointer's syntax because reference wasn't yet invented when 'this' was
introduced into language.

Juha Nieminen

unread,
Jun 14, 2018, 5:00:33 AM6/14/18
to
Tim Rentsch <t...@alumni.caltech.edu> wrote:
>> Object-oriented programming doesn't necessitate passing objects by pointer.
>
> I find this statement somewhat laughable. It's no accident
> that 'this' is a pointer rather than a value.

I quite often use object-oriented programming, sometimes with virtual
functions and all, without handling objects by pointer, but by value.

'this' might act similarly to a const pointer, but it's rare to even
need to refer to it explicitly. Even when you do, it can be the only
exception.

Melzzzzz

unread,
Jun 14, 2018, 2:59:02 PM6/14/18
to
What's wrong with pointers? At least you can check if this is null ;)

--
press any key to continue or any other to quit...

Paavo Helde

unread,
Jun 14, 2018, 3:17:57 PM6/14/18
to
This check tends to get optimized away nowadays by some compilers.

Melzzzzz

unread,
Jun 14, 2018, 3:34:19 PM6/14/18
to
Bah. That's nasty.

David Brown

unread,
Jun 14, 2018, 3:40:48 PM6/14/18
to
Null pointer checks get optimised away if it is safe to optimise them
away. If the pointer could legally be null, the check is carried out -
if you've already demonstrated that it cannot possibly be null, the
check is skipped. That seems fair enough to me.


Öö Tiib

unread,
Jun 14, 2018, 8:33:08 PM6/14/18
to
The logic of those compilers is that it can't legally be null, the same
way as references can not be legally null. The only way a 'this'
can be null is when some code in the program has called nonstatic method
of class through a null-pointer. Doing that is explicitly stated to be
undefined behavior. Unless the implementation has defined it (as an
extension) it may as well optimize such checks out.

David Brown

unread,
Jun 15, 2018, 2:24:10 AM6/15/18
to
Exactly - only "this" is only one case in a more general optimisation.

Tim Rentsch

unread,
Jun 21, 2018, 4:00:51 PM6/21/18
to
The distinction between a pointer and a reference is not
important to what I was saying.

Tim Rentsch

unread,
Jun 21, 2018, 4:11:29 PM6/21/18
to
Juha Nieminen <nos...@thanks.invalid> writes:

> Tim Rentsch <t...@alumni.caltech.edu> wrote:
>
>>> Object-oriented programming doesn't necessitate passing objects by pointer.
>>
>> I find this statement somewhat laughable. It's no accident
>> that 'this' is a pointer rather than a value.
>
> I quite often use object-oriented programming, sometimes with virtual
> functions and all, without handling objects by pointer, but by value.

I think you are confused. Virtual functions don't work if the
receiver of a message send is a value ratther than through a
pointer/referece.

> 'this' might act similarly to a const pointer, but it's rare to even
> need to refer to it explicitly.

Explicitness is irrelevant to my comment.

> Even when you do, it can be the only exception.

Fine but the exception is crucial! The message recipient being
referred to by pointer or reference is what makes the receiver
an object.

Tim Rentsch

unread,
Jun 21, 2018, 4:14:22 PM6/21/18
to
Do you have a point here?

If your point is that arbitrary control flow can be simulated
by a loop and a case statement, that is true, and also
obvious. But it is quite beside the point of my comment.
Do you see why?

Siri Cruise

unread,
Jun 21, 2018, 4:51:59 PM6/21/18
to
In article <kfnmuvn...@x-alumni2.alumni.caltech.edu>,
You can use gotos even when the language doesn't have gotos.

Rosario19

unread,
Jun 22, 2018, 2:18:40 PM6/22/18
to
On Thu, 21 Jun 2018 13:11:17 -0700, Tim Rentsch wrote:

>Juha Nieminen <nos...@thanks.invalid> writes:
>
>> Tim Rentsch <t...@alumni.caltech.edu> wrote:
>>
>>>> Object-oriented programming doesn't necessitate passing objects by pointer.
>>>
>>> I find this statement somewhat laughable. It's no accident
>>> that 'this' is a pointer rather than a value.
>>
>> I quite often use object-oriented programming, sometimes with virtual
>> functions and all, without handling objects by pointer, but by value.

someone can to clear this?

i don't know even what "virtual" means, nor interst me; but i'm
interested in the question on objects...

in the few seems to me to be the situation

one obj has to be a space of memory one address start one address end
and all to code and decode it

so all the objs has to have one pointer to them or one reference

so when i pass one number to one function that use reference example

for example we have int f(int& a){...}

f(23)

this is not ok

23 is not one obj is just one immediate i pass to the function
(even if 23 is push in the stack it is one obj
but the compiler not think so)


so the compiler it seems has need of create one obj, fill it with
value 23
and pass its address in the function in a way i not see

"f(23)" means, "{Int t(23); f(t);}"
-----------------------------

int t=23;

f(t)

ok pass one obj to f

Juha Nieminen

unread,
Jun 25, 2018, 8:36:35 AM6/25/18
to
Tim Rentsch <t...@alumni.caltech.edu> wrote:
>> I quite often use object-oriented programming, sometimes with virtual
>> functions and all, without handling objects by pointer, but by value.
>
> I think you are confused. Virtual functions don't work if the
> receiver of a message send is a value ratther than through a
> pointer/referece.

Of course they work. (Well, unless you consider the implicit use of
'this' to be using the object "by pointer".)

//--------------------------------------------------------
class Base
{
public:
void foo() { anotherFunction(); }

protected:
virtual void anotherFunction()
{ defaultImplementation; }
};

class Derived: public Base
{
protected:
virtual void anotherFunction() override
{ customImplementation; }
};

...

Base obj1;
Derived obj2;
obj1.foo();
obj2.foo();
//--------------------------------------------------------

Juha Nieminen

unread,
Jun 25, 2018, 8:41:33 AM6/25/18
to
Rosario19 <R...@invalid.invalid> wrote:
> so when i pass one number to one function that use reference example
>
> for example we have int f(int& a){...}
>
> f(23)
>
> this is not ok
>
> 23 is not one obj is just one immediate i pass to the function
> (even if 23 is push in the stack it is one obj
> but the compiler not think so)

That's not exactly what's happening. If you change your "int&" to a
"const int&", you'll see that it compiles and works ok.

The reason why the non-const version doesn't compile is that the language
doesn't like non-const references to temporaries. This is disallowed
in the standard. (You can still ignore the standard and cast away
the constness inside that function, but then all bets are off, and
the standard doesn't guarantee what will happen. It might work, it
might crash, or it might do something else at random.)

Tim Rentsch

unread,
Jun 30, 2018, 1:23:08 PM6/30/18
to
I see. I didn't understand what point it was you were
originally trying to get at.

Tim Rentsch

unread,
Jun 30, 2018, 1:27:06 PM6/30/18
to
Rosario19 <R...@invalid.invalid> writes:

> On Thu, 21 Jun 2018 13:11:17 -0700, Tim Rentsch wrote:
>
>> Juha Nieminen <nos...@thanks.invalid> writes:
>>
>>> Tim Rentsch <t...@alumni.caltech.edu> wrote:
>>>
>>>>> Object-oriented programming doesn't necessitate passing objects by
>>>>> pointer.
>>>>
>>>> I find this statement somewhat laughable. It's no accident
>>>> that 'this' is a pointer rather than a value.
>>>
>>> I quite often use object-oriented programming, sometimes with virtual
>>> functions and all, without handling objects by pointer, but by value.
>
> someone can to clear this?
>
> i don't know even what "virtual" means, nor interst me; but i'm
> interested in the question on objects... [...]

What you're asking about is different from the topic
being discussed in what you're responding to. I don't
have anything to say on what you're asking about (if
I understand what it is, which I'm not sure if that's
true).

Tim Rentsch

unread,
Jun 30, 2018, 1:28:27 PM6/30/18
to
Juha Nieminen <nos...@thanks.invalid> writes:

> Tim Rentsch <t...@alumni.caltech.edu> wrote:
>
>>> I quite often use object-oriented programming, sometimes with virtual
>>> functions and all, without handling objects by pointer, but by value.
>>
>> I think you are confused. Virtual functions don't work if the
>> receiver of a message send is a value ratther than through a
>> pointer/referece.
>
> Of course they work. (Well, unless you consider the implicit use of
> 'this' to be using the object "by pointer".)

It is! That is exactly the point.

Siri Cruise

unread,
Jun 30, 2018, 1:34:41 PM6/30/18
to
In article <kfnbmbs...@x-alumni2.alumni.caltech.edu>,
Tim Rentsch <t...@alumni.caltech.edu> wrote:

> >>>>>>> You can code in Fortran 66 no matter what language you use.
> >>>>>>
> >>>>>> Not in Python. Or any language that has decided it knows best and has
> >>>>>> got
> >>>>>> rid
> >>>>>> of 'goto', even though it's one of the simplest features to implement.

> I see. I didn't understand what point it was you were
> originally trying to get at.

Python is a special.

Juha Nieminen

unread,
Jul 1, 2018, 2:11:43 PM7/1/18
to
If you are going to nitpick like that, then there is no "by value"
manipulation of objects in C++ at all. All member functions get an
implicit 'this' "pointer", and all member variables are accessed
through it.

Tim Rentsch

unread,
Jul 18, 2018, 2:46:49 PM7/18/18
to
You think that's nitpicking? Is your understanding that shallow?

The difference is essential because passing an object by value
throws away dynamic type information. Any object passed by value
has a dynamic type that is the same as its static type. Virtual
function calls are dynamic only when the dynamic type is (at
least potentially) different than the static type. Passing an
object by pointer/reference is necessary for dynamic dispatch
of virtual functions actually to be dynamic rather than static.

Mr Flibble

unread,
Jul 18, 2018, 5:09:25 PM7/18/18
to
What you are saying is only applicable if slicing occurs otherwise it is
perfectly fine to pass objects by value albeit accepting that copies are
being made.

/Flibble

--
"Suppose it’s all true, and you walk up to the pearly gates, and are
confronted by God," Bryne asked on his show The Meaning of Life. "What
will Stephen Fry say to him, her, or it?"
"I’d say, bone cancer in children? What’s that about?" Fry replied.
"How dare you? How dare you create a world to which there is such misery
that is not our fault. It’s not right, it’s utterly, utterly evil."
"Why should I respect a capricious, mean-minded, stupid God who creates a
world that is so full of injustice and pain. That’s what I would say."

Juha Nieminen

unread,
Jul 26, 2018, 1:55:53 AM7/26/18
to
Tim Rentsch <t...@alumni.caltech.edu> wrote:
> You think that's nitpicking? Is your understanding that shallow?
>
> The difference is essential because passing an object by value
> throws away dynamic type information. Any object passed by value
> has a dynamic type that is the same as its static type. Virtual
> function calls are dynamic only when the dynamic type is (at
> least potentially) different than the static type. Passing an
> object by pointer/reference is necessary for dynamic dispatch
> of virtual functions actually to be dynamic rather than static.

In the example I gave there's a virtual function, and the base
class implementation calls either its own implementation or a
derived class implementation depending on the situation (ie.
depending on which kind of object it is). Yet no passing
by reference or by pointer was performed. No "throwing
away dynamic type information" happened.

Alf P. Steinbach

unread,
Jul 26, 2018, 3:23:34 AM7/26/18
to
Tim's got a point because slicing, which can happen with pass by value,
throws away information about the original type.

Juha's goat a point because the virtual function mechanism continues to
work in the copied objects.

I believe you both are aware of the other's technical possibility, but
maybe don't realize that that's what the other one is talking about.


Cheers!,

- Alf


Tim Rentsch

unread,
Aug 6, 2018, 8:24:26 AM8/6/18
to
What I think you're saying is that if the dynamic type matches
the static type then the same function will be called. That's
true, but then it also doesn't matter whether the functions are
virtual or not: the binding is the same as non-virtual binding.
Moreover there is another change in that any members referred to
will be separate from the original members when the argument is
passed by value rather than by reference. Sometimes this
matters, sometimes it doesn't, but certainly for some cases the
behavior will change in a way that is very un-object like.

Tim Rentsch

unread,
Aug 6, 2018, 9:50:23 AM8/6/18
to
Here is your example code (indented but otherwise unchanged):

class Base
{
public:
void foo() { anotherFunction(); }

protected:
virtual void anotherFunction()
{ defaultImplementation; }
};

class Derived: public Base
{
protected:
virtual void anotherFunction() override
{ customImplementation; }
};

...

Base obj1;
Derived obj2;
obj1.foo();
obj2.foo();

Your statement that there is no passing by reference or by
pointer is wrong. The calls obj1.foo() and obj2.foo() are both
calls by reference (ie, by pointer). All calls to non-static
member functions, whether using . or -> or ->* or implicitly
through 'this', are _always_ by pointer/reference, not by value.
There is no way to get value semantics using calls to member
functions (ie, non-static member functions). To get value
semantics the called function needs to be a regular function (or
a static member function), so the passed object is explicit
rather than implicit:

#include <iostream>

class Base {
public:
virtual void whatsit(){ std::cout << " Base\n"; }
};

class Derived : public Base {
public:
virtual void whatsit(){ std::cout << " Derived\n"; }
};

void
foo_by_reference( Base & blah ){
blah.whatsit();
}

void
foo_by_value( Base blah ){
blah.whatsit();
}

int
main(){
Base base;
Derived derived;

std::cout << "\ncalling by reference - base, then derived:\n";
foo_by_reference( base );
foo_by_reference( derived );

std::cout << "\ncalling by value - base, then derived:\n";
foo_by_value( base );
foo_by_value( derived );
}

Running this program shows that call by value and call by
reference behave differently.

To see that the original example passes by reference, have the
called function change a member of the called object:

#include <iostream>

class Base {
public:
int x;
Base() : x(0) {}
void foo(){ set_x(); }
virtual void set_x(){ x = 1; }
};

class Derived : public Base {
public:
virtual void set_x(){ x = -1; }
};

int
main(){
Base base;
std::cout << "\nfor base:\n";
std::cout << " before calling foo(), x is " << base.x << "\n";
base.foo();
std::cout << " before calling foo(), x is " << base.x << "\n";

Derived derived;
std::cout << "\nfor derived:\n";
std::cout << " before calling foo(), x is " << derived.x << "\n";
derived.foo();
std::cout << " before calling foo(), x is " << derived.x << "\n";
}

Calling base.foo(), or derived.foo(), changes the member 'x' in
the original object. The only way this can happen is if the
original object (ie, 'base' or 'derived') is passed by reference
(or pointer). Running this program shows that calls through
the "." operator pass the receiving object by reference/pointer,
not by value.

Tim Rentsch

unread,
Aug 6, 2018, 10:00:00 AM8/6/18
to
"Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:

> On 26.07.2018 07:55, Juha Nieminen wrote:
>
>> Tim Rentsch <t...@alumni.caltech.edu> wrote:
>>
>>> You think that's nitpicking? Is your understanding that shallow?
>>>
>>> The difference is essential because passing an object by value
>>> throws away dynamic type information. Any object passed by value
>>> has a dynamic type that is the same as its static type. Virtual
>>> function calls are dynamic only when the dynamic type is (at
>>> least potentially) different than the static type. Passing an
>>> object by pointer/reference is necessary for dynamic dispatch
>>> of virtual functions actually to be dynamic rather than static.
>>
>> In the example I gave there's a virtual function, and the base
>> class implementation calls either its own implementation or a
>> derived class implementation depending on the situation (ie.
>> depending on which kind of object it is). Yet no passing
>> by reference or by pointer was performed. No "throwing
>> away dynamic type information" happened.
>
> Tim's got a point because slicing, which can happen with pass by
> value, throws away information about the original type.
>
> Juha's goat a point because the virtual function mechanism continues
> to work in the copied objects.

His example is broken. The objects there are passed by reference
(ie by pointer), not copied. My response to his posting gives
more details.

> I believe you both are aware of the other's technical possibility,
> but maybe don't realize that that's what the other one is talking
> about.

AFAICT he is just confused. His example doesn't show anything
about what happens when objects are copied, because no copying
occured.

Alf P. Steinbach

unread,
Aug 6, 2018, 10:24:33 AM8/6/18
to
On 06.08.2018 14:24, Tim Rentsch wrote:
> Mr Flibble <flibbleREM...@i42.co.uk> writes:
>
> [snip]
> What I think you're saying is that if the dynamic type matches
> the static type then the same function will be called. That's
> true, but then it also doesn't matter whether the functions are
> virtual or not: the binding is the same as non-virtual binding.

No.

For example, a non-virtual base class member function can call a virtual
base class member function, with the call resolved to an implementation
in some derived class.

The resolution of that and /any/ virtual call within any object is
fixed, determined by the most derived object type. Find a context where
you know that type and you know where a call will end up. However, the
code at the call site will generally not have that knowledge, and can't
be retrospectively and dynamically equipped with such knowledge.


> Moreover there is another change in that any members referred to
> will be separate from the original members when the argument is
> passed by value rather than by reference. Sometimes this
> matters, sometimes it doesn't, but certainly for some cases the
> behavior will change in a way that is very un-object like.

Doesn't make sense to me, sorry.

Are you saying that when you make a copy, the copy will be a copy, and
that that is “very un-object like”?


Cheers!,

- Alf

Tim Rentsch

unread,
Aug 6, 2018, 1:34:22 PM8/6/18
to
"Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:

> On 06.08.2018 14:24, Tim Rentsch wrote:
>
>> Mr Flibble <flibbleREM...@i42.co.uk> writes:
>>
>> [snip]
>> What I think you're saying is that if the dynamic type matches
>> the static type then the same function will be called. That's
>> true, but then it also doesn't matter whether the functions are
>> virtual or not: the binding is the same as non-virtual binding.
>
> No.
>
> For example, a non-virtual base class member function can call a
> virtual base class member function, with the call resolved to an
> implementation in some derived class.
>
> The resolution of that and /any/ virtual call within any object is
> fixed, determined by the most derived object type. Find a context
> where you know that type and you know where a call will end
> up. However, the code at the call site will generally not have that
> knowledge, and can't be retrospectively and dynamically equipped with
> such knowledge.

You're talking about something different than what I was talking
about. In a function like this (whether it is a member function
doesn't matter, because the only object of interest is the
parameter):

void
foo( SomeClass blah ){
...
}

any member function call 'blah.something(...)' (ie, directly
inside the definition of foo()) does not depend on whether the
member function something() is virtual or not. Which function is
called can be determined statically, by looking at the class
hierarchy of SomeClass and its base classes, etc.

If the parameter is a reference rather than a value:

void
bas( SomeClass & blah ){
...
}

and there is a call to bas() where (this is important) the
dynamic type of the argument is SomeClass, the same thing is
true: any member function calls 'blah.something(...)' in the
definition of bas() do not depend on whether the member function
something() is virtual or not -- which function gets called is
the same as in the foo() case. (That property holds even though
we may not actually know at compile time that it does.)

This observation may seem trivial and obvious, but it's really
all I was saying there.

>> Moreover there is another change in that any members referred to
>> will be separate from the original members when the argument is
>> passed by value rather than by reference. Sometimes this
>> matters, sometimes it doesn't, but certainly for some cases the
>> behavior will change in a way that is very un-object like.
>
> Doesn't make sense to me, sorry.
>
> Are you saying that when you make a copy, the copy will be a copy,
> and that that is ?very un-object like??

I gave an example in my response to Juha Nieminen.

For another example, consider a garden variety use of cout -

std::cout << "X is " << x << " and y is " << y << "\n";

If cout is copied rather than passed by reference, then any
updates to its state will be lost. Rather than being buffered
the argument strings and values will be dropped on the floor,
and no output will occur.

Of course it is possible that cout could be implemented so that
copying wouldn't matter; for example, it could have just a
single member that is a pointer (or reference) off to the "real"
state. But that's just call by reference in disguise. For
objects to act like objects as we know them, somewhere there
needs to be call by reference (or pointer), not by value.

Does that make more sense now?

Vir Campestris

unread,
Aug 7, 2018, 5:57:57 PM8/7/18
to
I've read that 3 times, and I still don't follow what you mean.

In the first case, blah is a SomeClass object constructed locally. It
may well have been copy constructed from a derived class, but its type
is SomeClass.

In the second case, blah is a reference (which is a pointer, but
prettier) to something _derived from_ SomeClass - including a SomeClass
object.

So if you have
DerivedClass: public SomeClass
{
retval something(params)
}
and (this is important) SomeClass has
virtual retval something(params)

then in the second case you'll call DerivedClass::something just as you
would with a pointer, even though the pointer you have in your hand is
of type SomeClass&

<snip>

BTW Juha is on my small list of people I listen to here.

Andy

Tim Rentsch

unread,
Aug 8, 2018, 1:05:34 AM8/8/18
to
Did you miss the part where I said "the dynamic type of the
argument is SomeClass"? If the dynamic type is SomeClass,
the reference must refer to a SomeClass, not a DerivedClass.

> BTW Juha is on my small list of people I listen to here.

I regret the way my comments came out. Certain styles of
expression sometimes trigger me to respond more severely
than I mean to, and that happened here. I didn't mean to
malign Juha and am sorry it came across that way.

Vir Campestris

unread,
Aug 9, 2018, 6:23:27 PM8/9/18
to
On 08/08/2018 06:05, Tim Rentsch wrote:
> Vir Campestris <vir.cam...@invalid.invalid> writes:
>
>> On 06/08/2018 18:34, Tim Rentsch wrote:
>>
<snip>>>>
<snip>

bas cannot know the actual runtime type of the SomeClass reference. It's
possible an optimising compiler might work it out, in which case it can
omit the vtable activity, but the general case is it'll look in the
vtable (which is not very expensive) before making the call.

Andy

Tim Rentsch

unread,
Aug 14, 2018, 2:53:19 PM8/14/18
to
> reference. [.. elaboration ..]

That's true, but I didn't say it did. In fact I mentioned
already that this might not be known at compile time. Here is
that paragraph; note the last sentence:

and there is a call to bas() where (this is important) the
dynamic type of the argument is SomeClass, the same thing is
true: any member function calls 'blah.something(...)' in the
definition of bas() do not depend on whether the member function
something() is virtual or not -- which function gets called is
the same as in the foo() case. (That property holds even though
we may not actually know at compile time that it does.)

The point of the example is that when the dynamic type is the
same as the static type, virtualness doesn't matter as far as
calls in bas() itself is concerned. The same principle holds
whether an object is passed by reference or by value. But when
an object is passed by value, the dynamic type of the _parameter_
will /always/ be the same as its static type, because calls by
value discard any additional dynamic type that may have been
contained in the _argument_. Call by reference is essential for
the usual object-oriented mechanisms in C++ to work.
0 new messages