Reputation: 1047
I'm working on a C++ project where, among other things, I have an interface with a few pure virtual methods. The problem arises when I try to implement that interface - IntelliSense doesn't seem to agree with the derived class's method declaration. An example of such a method:
// DLL_EXPORT -> #define DLL_EXPORT __declspec(dllexport)
// IPlayer
DLL_EXPORT virtual const Grid& GetGrid() const = 0;
Declaration in one of the derived classes:
// Human : IPlayer
DLL_EXPORT const Grid& IPlayer::GetGrid() const;
The error it keeps nagging me with - "IntelliSense: declaration must correspond to a pure virtual member function in the indicated base class". The code compiles without errors and runs fine, all of the "problematic" methods do their jobs as expected during run time. What is worth mentioning is that the error disappears if I remove the IPlayer:: scope qualifier in the derived class. I wanted to keep it there for readability reasons. Also, I am NOT proficient in C++ so there could be something obviously wrong with the example I've provided.
Upvotes: 0
Views: 715
Reputation: 137425
Minimized example:
struct C { virtual void f() = 0; };
struct D : C { void C::f() { } };
This doesn't compile in any version of g++ or clang that I tested. Intellisense in VS2013 uses the EDG frontend, and to quote Jonathan Wakely, "If GCC, Clang and EDG all agree and MSVC disagrees that usually means MSVC is wrong."
To make things more interesting, the relevant paragraphs in the standard actually changed between C++11 and C++14.
In C++11, this is flat-out illegal (N3337 §8.3 [dcl.meaning]/p1):
A declarator-id shall not be qualified except for the definition of a member function (9.3) or static data member (9.4) outside of its class, the definition or explicit instantiation of a function or variable member of a namespace outside of its namespace, or the definition of an explicit specialization outside of its namespace, or the declaration of a friend function that is a member of another class or namespace (11.3).
This sentence was removed in C++14 as a result of CWG issue 482. The proposed resolution for that issue has the following note:
[Drafting note: The omission of “outside of its class” here does not give permission for redeclaration of class members; that is still prohibited by 9.2 [class.mem] paragraph 1. The removal of the enumeration of the kinds of declarations in which a qualified-id can appear does allow a typedef declaration to use a qualified-id, which was not permitted before; if that is undesirable, the prohibition can be reinstated here.]
In C++14, the only applicable rule in §8.3 [dcl.meaning]/p1 is now (quoting N3936):
When the declarator-id is qualified, the declaration shall refer to a previously declared member of the class or namespace to which the qualifier refers (or, in the case of a namespace, of an element of the inline namespace set of that namespace (7.3.1)) or to a specialization thereof; the member shall not merely have been introduced by a using-declaration in the scope of the class or namespace nominated by the nested-name-specifier of the declarator-id.
The relevant part of §9.2 [class.mem]/p1 is:
Except when used to declare friends (11.3) or to introduce the name of a member of a base class into a derived class (7.3.3), member-declarations declare members of the class, and each such member-declaration shall declare at least one member name of the class. A member shall not be declared twice in the member-specification, except that a nested class or member class template can be declared and then later defined, and except that an enumeration can be introduced with an opaque-enum-declaration and later redeclared with an enum-specifier.
Since a using-declaration "to introduce a member of a base class into a derived class" is made an explicit exception, it appears that base class members are not considered members for the purposes of the rule that "member-declarations declare members of the class, and each such member-declaration shall declare at least one member name of the class". If so, then it follows that using a qualified-id like void C::f() { }
in a member-declaration is also not allowed in C++14, since that qualified-id refers to a member of C
, not a member of D
.
Upvotes: 1