Here’s a class with an undefined method. It seems compilers allow instances of this class to be constructed, so long as the undefined member function is never called:
struct A {
void foo();
};
int main() {
A a; // <-- Works in both VC2013 and g++
a.foo(); // <-- Error in both VC2013 and g++
}
Here’s a similar situation, but one that involves inheritance. Subclass Bar
extends base class Foo
. Foo
defines a method g()
. Bar
declares the same-named method but does not define it:
#include <iostream>
struct Foo {
void g() { std::cout << "g\n"; }
};
struct Bar : Foo {
void g();
};
int main() {
Bar b; // Works in both VC2013 and g++
b.Foo::g(); // Works in both VC2013 and g++
b.g(); // Error in both VC2013 and g++
}
Here's a variation of the above. The only difference here is that g()
is virtual
to both Foo
and Bar
:
#include <iostream>
struct Foo {
virtual void g() { std::cout << "g\n"; }
};
struct Bar : Foo {
virtual void g();
};
int main() {
Bar b; // Works in g++. But not in VC2013, which gives
// 'fatal error LNK1120: 1 unresolved externals'
b.Foo::g(); // Works in g++, but VC2013 already failed on b's construction
b.g(); // Error in g++, but VC2013 already failed on b's construction
}
See the code comments for contrast of different behavior between VC2013 and g++.
virtual
keyword compared to the one in its version without the virtual
keyword?Bar
’s declaration of g()
count as overriding
even when Bar
doesn't provide a definition?Which compiler is correct, if any?
They are both right. Your code is wrong, no diagnostic required. [class.virtual]/11
A virtual function declared in a class shall be defined, or declared pure (10.4) in that class, or both; but no diagnostic is required (3.2).
[intro.compliance]/2:
If a program contains a violation of a rule for which no diagnostic is required, this International Standard places no requirement on implementations with respect to that program.
Have a look at your optimization settings for GCC, they may influence the behavior.
Are unused undefined methods always allowed?
A member function must be defined if and only if it is odr-used. [basic.def.odr]/3:
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required.
Now consider [basic.def.odr]/2:
An expression is potentially evaluated unless it is an unevaluated operand (Clause 5) or a subexpression thereof.
[…]
A virtual member function is odr-used if it is not pure.
A non-overloaded function whose name appears as a potentially-evaluated expression or a member of a set of candidate functions, if selected by overload resolution when referred to from a potentially-evaluated expression, is odr-used, unless it is a pure virtual function and its name is not explicitly qualified.
You are still allowed to use undefined non-virtual member functions inside decltype
or sizeof
. But non-pure virtual functions are odr-used simply because they are not pure.
Does Bar’s declaration of g() count as overriding even when Bar doesn't provide a definition?
Yes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With