Is a using-declaration supposed to hide an inherited virtual function?
struct level0
{
virtual void foo() = 0;
};
struct level1 : level0
{
virtual void foo() { cout <<" level1 " << endl; }
};
struct level2 : level1
{
virtual void foo() { cout <<" level2 " << endl; }
};
struct level3 : level2
{
using level1::foo;
};
int main()
{
level1* l1 = new level3;
l1->foo();
level3 l3;
l3.foo();
return 0;
}
the above code using gcc gives
level2
level1
but in icc gives
level2
level2
Which one is correct or is it undefined by standard?
Edit: This proves there is a bug for sure, consider the following main function
int main()
{
level3 l3;
l3.foo(); // This prints level1
level3* pl3 = &l3;
pl3->foo(); // This prints level2
level3& rl3 = l3;
rl3.foo(); // This prints level1
level3& rpl3 = *pl3;
rpl3.foo(); // This p开发者_Go百科rints level2
return 0;
}
So the same object when used directly produces different results and when used via a pointer of same type produces different results!!!
An example in Standard section 10.3p2 makes it clear that using declarations do not override virtual functions.
This is a known g++ bug.
As you noticed, when calling the member function via a reference or pointer, rather than a case in which the dynamic type is known, the bug does not happen.
using level1::foo;
introduces a foo
function in level3
class which refers to level1::foo
.
In a using-declaration used as a member-declaration, the nested-name-specifier shall name a base class of the class being defined. Such a using-declaration introduces the set of declarations found by member name lookup.
However, since level1::foo
is virtual, I guess that by calling it you should call level2::foo
, thus icc should be right.
I'm not so sure, anyway.
The way to get level1 level1 of course would be:
struct level3 : level2
{
virtual void foo() { level1::foo(); }
};
Your "using" directive seems to be informing the compiler that if you have a level3 and call foo on it, it should invoke the level1 version, but it is not overwriting this to the v-table.
gcc looks wrong because of the inconsistency, not sure about icc because I don't know what the standard indicates.
精彩评论