while compiling some code that I ran into a compiler error that seemed strange to me and relates to inheritance, nested classes, using declarations, and access modifiers.
Basically, the intention is for a derived type to expose a nested protected class of a base type.
The the following short example to demonstrate the issue:
class Base
{
protected:
struct Nested
{
enum value_enum
{
val = 0,
val2,
val3
};
};
};
class Derived : public Base
{
public:
using Base::Nested;
};
int main(int argc, char** argv)
{
//Base::Nested aa; // error, as (I) expected
//Base::Nested::value_enum ab; // error, as (I) expected
Derived::Nested ba; // works, as (I) expected
Derived::Nested::value_enum bb; // MSVC error, as (I) did not expect
return 0;
}
See live.
MSVC11 (v11.00.61030) chokes on this code with the following error:
error C2248: 'Base::Nested' : cannot access protected struct declared in class 'Base'
Both GCC and Clang compile this properly, so without the ability to quote the relevant parts from the standard, I would argue this is an MSVC bug.
Is there a way around this with MSVC?
A nested class can be declared with any access modifier, namely private, public, protected, internal, protected internal, or private protected.
This is given as follows. class A { public: class B { private: int num; public: void getdata(int n) { num = n; } void putdata() { cout<<"The number is "<<num; } }; }; In the function main(), an object of the class A and class B is defined. Then the functions getdata() and putdata() are called using the variable obj.
A nested class is a member and as such has the same access rights as any other member. The members of an enclosing class have no special access to members of a nested class; the usual access rules shall be obeyed. For example, program 1 compiles without any error and program 2 fails in compilation.
And like static class methods, a static nested class cannot refer directly to instance variables or methods defined in its enclosing class: it can use them only through an object reference. They are accessed using the enclosing class name. To instantiate an inner class, you must first instantiate the outer class.
For MSVC the following workaround works:
class Derived : public Base
{
public:
using Base::Nested;
typedef Base::Nested::value_enum value_enum; // add this
};
int main(int argc, char** argv)
{
//Base::Nested aa; // error, as (I) expected
//Base::Nested::value_enum ab; // error, as (I) expected
Derived::Nested ba; // works, as (I) expected
Derived::value_enum bb = Derived::value_enum::val; // now works in MSVC
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With