I had gotten an interesting reference (From:
How can I access public nested class methods from base class variables (C++, Visual Studio 2013)?
[1]) about the use of the keyword virtual; so I started looking into it a bit, and I found:
Virtual Inner Classes? - C++ Forum[2]
I tried copying that into visual studio and compiling it, and it worked fine; however, I use classes in my code versus struct in the example. Now, I figured that the use of struct and class would be very nearly the same, as long as I define the scope. Being lazy, I set the scope for each class to be defined as public to not incur any penalties. However, the code with the
class in it does not compile and induces a lot of errors, versus the code with
struct compiles fine.
For the purposes of the test, everything can be considered in one file.
The code that works is:
#include <iostream>
#include <memory>
namespace one
{
struct A
{
struct B
{
virtual ~B() {}
virtual void foo() = 0;
};
std::shared_ptr<B> bar(bool);
};
std::shared_ptr<A::B> A::bar(bool f)
{
struct C : A::B
{
C(int, int) {}
virtual void foo() override { std::cout << "one::A::bar::C::foo\n"; }
};
if (f) return std::make_shared<C>(3, 4);
else
{
struct D : C
{
D(int a, int b, int c) : C(a, b) {}
virtual void foo() override { std::cout << "one::A::bar::D::foo\n"; }
};
return std::make_shared<D>(10, 20, 30);
}
}
}
int main()
{
one::A a;
auto p = a.bar(false);
p->foo();
}
#endif
The code that does not compile is:
#include <iostream>
#include <memory>
namespace one
{
struct A
{
struct B
{
virtual ~B() {}
virtual void foo() = 0;
};
std::shared_ptr<B> bar(bool);
};
std::shared_ptr<A::B> A::bar(bool f)
{
struct C : A::B
{
C(int, int) {}
virtual void foo() override { std::cout << "one::A::bar::C::foo\n"; }
};
if (f) return std::make_shared<C>(3, 4);
else
{
struct D : C
{
D(int a, int b, int c) : C(a, b) {}
virtual void foo() override { std::cout << "one::A::bar::D::foo\n"; }
};
return std::make_shared<D>(10, 20, 30);
}
}
}
namespace two
{
class A
{
public:
class B
{
public:
virtual ~B() {}
virtual void foo() = 0;
};
std::shared_ptr<B> bar(bool);
};
std::shared_ptr<A::B> A::bar(bool f)
{
class C : A::B
{
public:
C(int, int) {}
virtual void foo() override { std::cout << "one::A::bar::C::foo\n"; }
};
if (f) return std::make_shared<C>(3, 4);
else
{
class D : C
{
public:
D(int a, int b, int c) : C(a, b) {}
virtual void foo() override { std::cout << "one::A::bar::D::foo\n"; }
};
return std::make_shared<D>(10, 20, 30);
}
}
}
int main()
{
one::A a;
auto p = a.bar(false);
p->foo();
}
#endif
The errors are: c2243 (see for detail:
Compiler Error C2243[
3])
1>------ Build started: Project: bmpLoad, Configuration: Debug Win32 ------
1> CDCDirectControls.cpp
1>c:\program files (x86)\microsoft visual studio 12.0\vc\include\memory(291): error C2243: 'type cast' : conversion from 'two::A::bar::C *' to 'two::A::B *' exists, but is inaccessible
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\memory(577) : see reference to function template instantiation 'std::_Ptr_base<_Ty>::_Ptr_base<two::A::bar::C>(std::_Ptr_base<two::A::bar::C> &&)' being compiled
1> with
1> [
1> _Ty=two::A::B
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\memory(577) : see reference to function template instantiation 'std::_Ptr_base<_Ty>::_Ptr_base<two::A::bar::C>(std::_Ptr_base<two::A::bar::C> &&)' being compiled
1> with
1> [
1> _Ty=two::A::B
1> ]
1> c:\users\stephen\desktop\stephen\cppprojects\samplemfc\bmpload\bmpload\cdcdirectcontrols.h(186) : see reference to function template instantiation 'std::shared_ptr<two::A::B>::shared_ptr<two::A::bar::C,void>(std::shared_ptr<two::A::bar::C> &&) throw()' being compiled
1> c:\users\stephen\desktop\stephen\cppprojects\samplemfc\bmpload\bmpload\cdcdirectcontrols.h(186) : see reference to function template instantiation 'std::shared_ptr<two::A::B>::shared_ptr<two::A::bar::C,void>(std::shared_ptr<two::A::bar::C> &&) throw()' being compiled
1>c:\program files (x86)\microsoft visual studio 12.0\vc\include\memory(291): error C2243: 'type cast' : conversion from 'two::A::bar::D *' to 'two::A::B *' exists, but is inaccessible
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\memory(577) : see reference to function template instantiation 'std::_Ptr_base<_Ty>::_Ptr_base<two::A::bar::D>(std::_Ptr_base<two::A::bar::D> &&)' being compiled
1> with
1> [
1> _Ty=two::A::B
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\memory(577) : see reference to function template instantiation 'std::_Ptr_base<_Ty>::_Ptr_base<two::A::bar::D>(std::_Ptr_base<two::A::bar::D> &&)' being compiled
1> with
1> [
1> _Ty=two::A::B
1> ]
1> c:\users\stephen\desktop\stephen\cppprojects\samplemfc\bmpload\bmpload\cdcdirectcontrols.h(196) : see reference to function template instantiation 'std::shared_ptr<two::A::B>::shared_ptr<two::A::bar::D,void>(std::shared_ptr<two::A::bar::D> &&) throw()' being compiled
1> c:\users\stephen\desktop\stephen\cppprojects\samplemfc\bmpload\bmpload\cdcdirectcontrols.h(196) : see reference to function template instantiation 'std::shared_ptr<two::A::B>::shared_ptr<two::A::bar::D,void>(std::shared_ptr<two::A::bar::D> &&) throw()' being compiled
1> Generating Code...
1> Skipping... (no relevant changes detected)
1> bmpLoadView.cpp
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
All the code is self-contained in one file.
1) How the code need to get rewritten using classes?
2) Why does it work with
struct but not with
class? (I thought the two were identical except for scope, but with
public: specifiers, they should act the same.)
Additional references are:
Virtual Inner Classes? - C++ Forum[3]
virtual function specifier - cppreference.com[4]