So I was recently trying to get a piece of C++ code to compile and I just could not figure out what was going on. Here's a sample roughly of what the code looked like. It's not quite the same code I was debugging, but it does spit out similar compiler outputs.
namespace space { template<typename type> class ClassA { protected: int bounds; public: virtual ~ClassA(void) { } virtual int doIt(void) = 0; virtual int doIt2(void) = 0; }; template<typename type> class ClassB : public ClassA<type> { protected: ClassA<type> *parent; public: virtual ~ClassB(void) { } virtual int doIt(void) { return bounds; } int doIt2(void) { return parent->bounds; } }; }
For the longest time I could not figure out why doIt2 wasn't calling properly. The actual code I was debugging was a bit more complicated, but I should have been able to quickly identify the problem and fix it.
The compiler message: 'ClassA::bounds' : cannot access protected member declared in class 'ClassA'
The message would highlight the access line in doIt2 where I try to retrieve the bounds value from parent. My first thought was that the problem might have to deal with C++ template types not being right since I'm not particularly well-versed with C++ templates. After double checking, then triple and quadruple checking the templates I decided that they were correct and that there must be some other problem. Needless to say, I chased red herring after red herring trying to figure out what was wrong.
So what was the actual problem? I forgot to declare ClassB as a friend to ClassA. This is one of those details that gets lost between Java programming and C++ programming. In Java, even though the field bounds is protected I can still access it from anywhere in the same package. The closest equivalent in C++ are namespaces, though these really aren't that close at all. So me being in a semi sleep-deprived state assumed (there's that magical 7 letter word which causes trouble) that I must be able to have access to bounds because not only was I in the same namespace, I was in the same file.
After taking a little break, I finally realized my mistake, shook my head and decided to write a blog post about the ordeal. Morale of the story? Take a break when you're stuck on a problem you just can't figure out. And get some sleep.
The fixed solution:
namespace space { template<typename type> class ClassB; template<typename type> class ClassA { protected: int bounds; public: virtual ~ClassA(void) { } virtual int doIt(void) = 0; virtual int doIt2(void) = 0; friend class ClassB<type>; }; template<typename type> class ClassB : public ClassA<type> { protected: ClassA<type> *parent; public: virtual ~ClassB(void) { } virtual int doIt(void) { return bounds; } int doIt2(void) { return parent->bounds; } }; }
No comments :
Post a Comment