【问题标题】:VS 2013 - IntelliSense reporting false positives?VS 2013 - IntelliSense 报告误报?
【发布时间】:2014-08-18 00:15:19
【问题描述】:

我正在开发一个 C++ 项目,其中除其他外,我有一个带有一些纯虚拟方法的接口。当我尝试实现该接口时出现问题 - IntelliSense 似乎不同意派生类的方法声明。这种方法的一个例子:

// DLL_EXPORT -> #define DLL_EXPORT __declspec(dllexport)
// IPlayer
DLL_EXPORT virtual const Grid& GetGrid() const = 0;

在派生类之一中声明:

// Human : IPlayer
DLL_EXPORT const Grid& IPlayer::GetGrid() const;

它一直困扰着我的错误 - “IntelliSense:声明必须对应于指定基类中的纯虚拟成员函数”。代码编译没有错误并且运行良好,所有“有问题的”方法在运行时都按预期工作。值得一提的是,如果我删除派生类中的 IPlayer::scope 限定符,错误就会消失。出于可读性的原因,我想保留它。另外,我不精通 C++,所以我提供的示例可能存在明显错误。

【问题讨论】:

  • 尝试正确限定纯虚拟GetGrid
  • 恭喜,您是第 981519406510 个发现 IntelliSense 经常损坏的用户。 :)
  • @OMGtechy 如果没有问题,您能否进一步解释您的建议?
  • 忽略我说的话,这是垃圾。不过, override 关键字可能会帮助您解决这个问题(它可能会给智能感知带来它需要的效果)
  • 我不认为 Intellisense 坏了。我认为是MSVC。 g++ 和 clang 都不接受这个。

标签: c++ visual-studio intellisense


【解决方案1】:

最小化的例子:

struct C { virtual void f() = 0; };

struct D : C { void C::f() { } };

这不会在我测试的任何版本的 g++ 或 clang 中编译。 VS2013 中的 Intellisense 使用 EDG 前端,对quote Jonathan Wakely,“如果 GCC、Clang 和 EDG 都同意而 MSVC 不同意,这通常意味着 MSVC 是错误的。”

为了让事情更有趣,标准中的相关段落实际上在 C++11 和 C++14 之间发生了变化。

在 C++11 中,这是完全非法的(N3337 §8.3 [dcl.meaning]/p1):

一个 declarator-id 除了定义一个 其外部的成员函数 (9.3) 或静态数据成员 (9.4) 类,函数的定义或显式实例化,或 命名空间之外的命名空间的变量成员,或 在其命名空间之外定义显式特化,或 作为另一个类成员的友元函数的声明 或命名空间 (11.3)。

由于CWG issue 482,这句话在 C++14 中被删除。针对该问题提出的解决方案有以下说明:

[起草说明:此处省略“类外”不代表 允许重新声明班级成员;那仍然是 9.2 [class.mem] 第 1 段禁止。删除 枚举类型的声明,其中一个qualified-id可以 出现确实允许 typedef 声明使用限定 ID,它 以前不允许;如果这是不可取的,该禁令可以 在这里恢复。]

在 C++14 中,§8.3 [dcl.meaning]/p1 中唯一适用的规则现在是(引用 N3936):

declarator-id 合格时,该声明应引用一个 先前声明的类或命名空间的成员 限定符指(或者,在命名空间的情况下,指 该命名空间的内联命名空间集(7.3.1))或专业化 其中;该成员不应仅由某位成员介绍 using-declaration 在由指定的类或命名空间范围内 declarator-idnested-name-specifier

§9.2 [class.mem]/p1 的相关部分是:

除非用于声明朋友(11.3)或介绍名字 基类的成员到派生类(7.3.3), member-declarations 声明类的成员,并且每个这样的成员 member-declaration 应声明至少一个成员名称 班级。成员不得在大会中两次申报 成员规范,嵌套类或成员类除外 模板可以先声明然后再定义,除了一个 枚举可以通过 opaque-enum-declaration 和 后来用枚举说明符重新声明。

由于using-declaration“将基类的成员引入派生类”是一个明确的例外,因此基类成员似乎不被视为成员规则“member-declarations声明类的成员,并且每个这样的member-declaration应声明至少一个类的成员名称”。如果是这样,那么在 C++14 中也不允许在 member-declaration 中使用像 void C::f() { } 这样的 qualified-id,因为 qualified-id 指的是C 的成员,而不是D 的成员。

【讨论】:

  • 有趣的是,非常量方法不会产生这个问题。 EDG 没听懂,我猜。示例 - DLL_EXPORT virtual void SetGrid(Grid val) = 0; -> DLL_EXPORT void IPlayer::SetGrid(Grid val);我想,这也可能无法用 g++ 或 clang 编译。无论如何,谢谢你的彻底回答——它确实解释了很多。
猜你喜欢
  • 1970-01-01
  • 2015-12-28
  • 1970-01-01
  • 1970-01-01
  • 2014-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多