【发布时间】:2011-05-07 22:49:34
【问题描述】:
C++03 3.2.2 ...如果对象或非重载函数的名称出现在可能求值的表达式中,则使用该对象或非重载函数。如果不是纯的,则使用虚成员函数...
然后在3.2.3 中,我们有: 每个程序都应包含该程序中使用的每个非内联函数或对象的一个定义;无需诊断。定义可以显式出现在程序中,可以在标准或用户定义库中找到,或者(在适当时)隐式定义(参见 12.1、12.4 和 12.8)。
内联函数应在使用它的每个翻译单元中定义。
按照我正在阅读的内容:不使用纯虚函数。 ODR 仅适用于使用的功能。这是否意味着以下内容是合法的?我猜答案是否定的,它没有,但我不明白为什么。
//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();
}
【问题讨论】:
-
这是否编译/链接?我觉得会有一个链接错误,因为重复的 struct A 实现。
-
@Rolland:你什么意思?类定义可能而且应该出现在使用该类的每个翻译单元中......
-
@Stephane Rolland:再次阅读标准:“每个程序都应包含该程序中使用的每个非内联函数 [...] 的确切定义”和“虚拟成员函数是如果它不纯,则使用”。这意味着如果一个虚成员函数是纯的,标准可能会被解释为不使用它,这将允许任意多个定义。
-
GCC 链接器确实给出了一个错误(即使没有
main.cpp),但是从标准中看不清楚甚至是错误的,这取决于if的含义。 -
@Stephanie:我想我们都同意这个例子违背了标准的意图,它确实会引起问题,这很好。讨论是关于标准的措辞是否意外忘记涵盖这种情况。
标签: c++ pure-virtual language-lawyer one-definition-rule