> 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?