A virtual member function is used if it is not pure?

被刻印的时光 ゝ 提交于 2020-01-12 07:42:07

问题


C++03 3.2.2 ...An object or non-overloaded function is used if its name appears in a potentially-evaluated expression. A virtual member function is used if it is not pure...

And then later in 3.2.3 we have: Every program shall contain exactly one definition of every non-inline function or object that is used in that program; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see 12.1, 12.4 and 12.8). An inline function shall be defined in every translation unit in which it is used.

Along the lines I am reading: a pure virtual function is not used. The ODR applies only to functions which are used. Doesn't this imply that the following would be legal? I am guessing the answer is no, it doesn't, but then I can't understand why.

//x.h
struct A
{
   virtual void f() = 0;
};

//y.cpp
#include "x.h"
void A::f()
{
}

//z.cpp
#include "x.h"
#include <iostream>
void A::f()
{
   std::cout << "Hello" << std::endl;
}

//main.cpp
#include "x.h"
struct B:A
{
   virtual void f()
   {
      A::f();
   }
};

int main()
{
   A* p = new B;
   p->f();
}

回答1:


The two clauses are not mutually exclusive. That a virtual function is used if it is not pure, does not mean that the converse holds. If a virtual function is pure it does not mean that it is necessarily not used. It may still be used "if its name appears in a potentially evaluated expression" such as in your example: A::f();.




回答2:


This code violates ODR. A::f is multiply defined. Hence it has UB.

Multiple definitions across translation units are only allowed for the following as per $3.2/5

There can be more than one definition of a class type (clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (clause 14), non-static function template (14.5.5), static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.4) in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements.




回答3:


As @Charles Bailey pointed out, your A::f is in fact used even though it's pure virtual. But that's beside the main point.

It's not accurate that the One Definition Rule does not apply to functions that are not used. We have:

3.2p1 No translation unit shall contain more than one definition of any variable, function, class type, enumeration type or template.

3.2p3 Every program shall contain exactly one definition of every non-inline function or object that is used in that program; no diagnostic required.

Together, these requirements seem to imply that a used function must have exactly one definition, and an unused function (including a pure virtual function which is never explicitly called) may have either no definition or a single definition. In either case, multiple definitions for a non-inline function makes the program ill-formed.

At least, I'm quite certain that's the intent. But you may be on to a hole in the phrasing, since a very literal reading does not say anywhere that multiple different definitions of the same unused function in different translation units is ill-formed.

// x.cpp
void f() {}
void g() {}

// y.cpp
#include <iostream>
void f() {
  std::cout << "Huh" << std::endl;
}
void h() {}

// z.cpp
void g();
void h();
int main() { 
  g();
  h();
  return 0;
}



回答4:


This is related but off-topic: from the citations it seems there is a hole in the Standard alright: it should also say a pure virtual destructor is used, and, that it must be defined; at least if there exist any derived class objects which are destroyed or if a destructor of such is defined, since the derived class destructor must call the base destructor, implicitly it does so with the qualified::id syntax. The definition of such destructors is usually trivial but cannot be elided and cannot be generated.




回答5:


[class.abstract]: "A pure virtual function need be defined only if called with, or as if with (12.4), the qualified-id syntax (5.1)."

Your A::f is called by B::f, so there must be a single definition of A::f.



来源:https://stackoverflow.com/questions/4145915/a-virtual-member-function-is-used-if-it-is-not-pure

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!