I've come across a peculiar case while designing my C++ object inheritance tree in a project. I expected the below to fail:
struct A {
protected:
struct C { };
};
struct B: A {
struct C { };
};
But, this compiles just fine. Is this like an override? I can see how this isn't ambiguous because they can be specified as A::C
and B::C
, but how does this act in polymorphic cases? Will it call the prescribed type's C or the instance's type's C? As in, suppose this code below works and func
exists in both implementations of C:
A x = B();
decltype(x)::C::func();
which C would have their function called? More generally, is their a resource that describes how code snippets like these resolve?
This is fine, because you have two unrelated struct C
: the one is B::C
and the other B::A::C
. C
is just their shortcut name.
If you would have a static function f() defined in each C, you would be able to call it from outside the struct and without any object, as you have shown in your code:
A a = B(); // the type of a is A (B is sliced, by the way)
decltype(a)::C::f(); // so this calls A::C::f()
Now for the sake of completeness, here a more developed example that shows that at no point there is an ambiguity:
struct A {
struct C { static void f() { cout << "A::C::f" <<endl; } };
};
struct B: A {
C c1; // the only C known here is A::C
struct C { static void f() { cout << "B::C::f" <<endl; }}; // now B::C hides A::C
C c2; // so here the closest C known is B::C
A::C c3; // and here I can be explicit about the C I want
using D=A::C; // and here another way to be explicit:
D c4;
};
int main() {
B b;
decltype(b.c1)::C::f(); // A
decltype(b.c2)::C::f(); // B
}