- Title
- Calls via pointers to virtual member functions
- Status
- cd1
- Section
- 7.6.1.3 [expr.call]
- Submitter
- Martin O'Riordan
Created on 1999-05-17.00:00:00 last changed 217 months ago
Messages
Date: 2008-06-15.00:00:00
[Voted into the WP at the June, 2008 meeting.]
Date: 2008-02-15.00:00:00
Proposed resolution (February, 2008): Change 7.6.1.3 [expr.call] paragraph 1 as follows: Change 7.6.4 [expr.mptr.oper] paragraph 4 as follows:
... For a member function call, the postfix expression shall be an
implicit (11.4.3 [class.mfct.non.static], 11.4.9 [class.static]) or
explicit class member access (7.6.1.5 [expr.ref]) whose
id-expression is a function member name, or a pointer-to-member
expression (7.6.4 [expr.mptr.oper]) selecting a function member
.
The first expression in the postfix expression is then called the
object expression, and; the call is as a member of
the object pointed to or referred to by the object expression
(7.6.1.5 [expr.ref], 7.6.4 [expr.mptr.oper]). In the
case of an implicit class member access, the implied object is the one
pointed to by this . [Note: a member function call of
the form f() is interpreted as (*this).f() (see
11.4.3 [class.mfct.non.static]). —end note] If a function or
member function name is used, the name can be overloaded (
Clause 12 [over]), in which case the appropriate function shall
be selected according to the rules in 12.2 [over.match]. The function called in a member function call is
normally selected according to the static type of the object
expression (11.7 [class.derived]), but if that function
is virtual and is not specified using a qualified-id
then the function actually called will be the final overrider
(11.7.3 [class.virtual]) of the selected function in the dynamic
type of the object expression If the selected function is
non-virtual, or if the id-expression in the class member access
expression is a qualified-id, that function is called.
Otherwise, its final overrider (11.7.3 [class.virtual]) in the
dynamic type of the object expression is called. ...
The first operand is called the object expression. If
the dynamic type of the object expression does not contain the
member to which the pointer refers, the behavior is undefined.
Date: 2002-10-15.00:00:00
Notes from October 2002 meeting: This was moved back to open for lack of a champion. Martin O'Riordan
is not expected to be attending meetings.
Date: 2026-07-27.15:54:01
Martin O'Riordan:
Having gone through all the relevant references in the IS, it is not
conclusive that a call via a pointer to a virtual member function
is polymorphic at all, and could legitimately be
interpreted as being static. Consider 7.6.1.3 [expr.call] paragraph 1:
Yet other references such as
7.6.4 [expr.mptr.oper] paragraph 4:
Andy Sawyer:
Assuming the resolution is what I've assumed it is for the
last umpteen years (i.e. it does the polymorphic thing), then
the follow on to that is "Should there also be a way of selecting
the non-polymorphic behaviour"?
Mike Miller:
It might be argued that the current wording of
7.6.1.3 [expr.call] paragraph 1
does give
polymorphic behavior to simple calls via pointers to members.
(There is no qualified-id in obj.*pmf , and the IS says
that if the function is not specified using a qualified-id, the
final overrider will be called.) However, it clearly says the wrong
thing when the pointer-to-member itself is specified using a
qualified-id ( obj.*X::pmf ).
Bill Gibbons:
The phrase qualified-id in
7.6.1.3 [expr.call] paragraph 1
refers to the
id-expression and not to the "pointer-to-member expression"
earlier in the paragraph:
Mike Miller:
To be clear, here's an example:
The function called in a member function call is normally selected
according to the static type of the object expression (
11.7 [class.derived]
), but if that function is
virtual and is not specified using a qualified-id then
the function actually called will be the final overrider
(11.7.3 [class.virtual]
) of the selected
function in the dynamic type of the object expression.
Here it is quite specific that you get the polymorphic call only if you use
the unqualified syntax. But, the address of a member function is "always"
taken using the qualified syntax, which by inference would indicate that
call with a PMF is static and not polymorphic! Not what was intended.
If the dynamic type of the object does not contain the member to which
the pointer refers, the behavior is undefined.
indicate that the opposite may have been intended, by stating that it is the
dynamic type and not the static type that matters. Also,
7.6.4 [expr.mptr.oper] paragraph 6:
If the result of .* or ->* is a function,
then that result can be used
only as the operand for the function
call operator (). [Example:
which also implies that it is the object pointed to that determines both the
validity of the expression (the static type of ' ptr_to_obj '
may not have a
compatible function) and the implicit (polymorphic) meaning. Note too,
that this is stated in the non-normative example text.
(ptr_to_obj->*ptr_to_mfct)(10);
calls the member function denoted by ptr_to_mfct
for the object pointed
to by ptr_to_obj . ]
For a member function call, the postfix expression shall be an
implicit (11.4.3 [class.mfct.non.static]
,
11.4.9 [class.static]
) or explicit class member
access (7.6.1.5 [expr.ref]
) whose
id-expression is a function member name, or a pointer-to-member
expression (7.6.4 [expr.mptr.oper]
) selecting
a function member.
struct S {
virtual void f();
};
void (S::*pmf)();
void g(S* sp) {
sp->f(); // 1: polymorphic
sp->S::f(); // 2: non-polymorphic
(sp->S::f)(); // 3: non-polymorphic
(sp->*pmf)(); // 4: polymorphic
(sp->*&S::f)(); // 5: polymorphic
}
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2008-10-05 00:00:00 | admin | set | status: dr -> cd1 |
| 2008-07-27 00:00:00 | admin | set | messages: + msg1740 |
| 2008-06-29 00:00:00 | admin | set | status: ready -> dr |
| 2008-03-17 00:00:00 | admin | set | status: review -> ready |
| 2008-02-03 00:00:00 | admin | set | messages: + msg1576 |
| 2008-02-03 00:00:00 | admin | set | status: open -> review |
| 2002-11-08 00:00:00 | admin | set | messages: + msg759 |
| 2002-11-08 00:00:00 | admin | set | status: drafting -> open |
| 2000-02-23 00:00:00 | admin | set | status: open -> drafting |
| 1999-05-17 00:00:00 | admin | create | |