문제

I have a situation where I want to hide a base class and limit the classes that can inherit from it:

namespace _detail {
    class Private abstract final {
        struct Base abstract {
        protected:
            Base() {}
        };

        friend struct ::A;
        friend struct ::B;
        friend struct ::C;
    };
}

struct A : _detail::Private::Base {}; //error
struct B : _detail::Private::Base {}; //error
struct C : _detail::Private::Base {}; //error

The compiler tells me that _detail::Private::Base is inaccessible to A, B and C even though they are friends with Private. I've used this sort of pattern before without an issue, and can't really see what's different here compared to the other times I've used it. What am I not seeing?

도움이 되었습니까?

해결책

C++ language does not allow you to use qualified names (like ::A) in friend declarations, unless these qualified names refer to previously declared entities. Actually, this rule is applied virtualy everywhere, not only in friend declarations: qualified names have to refer to previously declared entities.

In your case you used qualified name ::A in friend declaration friend struct ::A. For that to work, struct A from global namespace has to be known to the compiler beforehand. In your case A is not declared at that point, which makes friend struct ::A declaration ill-formed. It should not even compile by formal rules of the language.

If your compiler accepts this, you have to consult your compiler documentatuion to figure out what it means. I suspect that friend struct ::A for unknown ::A is interpreted as equivalent to friend struct A, i.e. it declares _detail::A as friend.

If you make a forward declaration struct A; before declaring namespace _detail, it might make it work as intended.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top