Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are all unused undefined methods allowed?

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++.

  1. Which compiler is correct, if any?
  2. Why does VC2013's compiler have some different complaints in its version with the virtual keyword compared to the one in its version without the virtual keyword?
  3. Are unused undefined methods always allowed? If not, what are all the cases in which they're not allowed?
  4. Does Bar’s declaration of g() count as overriding even when Bar doesn't provide a definition?
like image 920
CodeBricks Avatar asked Nov 07 '14 22:11

CodeBricks


1 Answers

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.

like image 162
Columbo Avatar answered Sep 22 '22 15:09

Columbo