简体   繁体   English

使所有派生的模板类与C ++中的其他类成为朋友

[英]Make all derived template classes friend of other class in C++

Let's say I have to following hierarchy: 假设我必须遵循以下层次结构:

template<class T> class Base {
protected:
    T container;
};

template<class T> class Derived1 : public Base<T> {
public:
    void f1() {
        /* Does stuff with Base<T>::container */
    }
};

template<class T> class Derived2 : public Base<T> {
public:
    void f2() {
        /* Does stuff with Base<T>::container */
    }
};

Now I want an independent Class (not derived from Base) that can access the Base<T>::container directly from Base or any Derived class. 现在,我想要一个独立的类(不是从Base派生的),该类可以直接从Base或任何派生类访问Base<T>::container I read about template friend classes and it seems to be the solution to my problem but I couldn't figure out the syntax yet. 我阅读了有关模板朋友类的文章 ,这似乎是解决我的问题的方法,但是我还无法弄清楚语法。 I am looking for something like: 我正在寻找类似的东西:

template<class T> class Foo{
    template<T> friend class Base<T>; // <-- this does not work
public:
    size_t bar(const Base<T> &b) const{
        return b.container.size();
    }
};

Derived1<std::vector<int> > d;
d.f1();
Foo<std::vector<int> > foo;
size_t s = foo.bar()

The friend class line causes an error: specialization of 'template<class T> class Base' must appear at namespace scope template<T> friend class Base<T> and the member variable container is still not accessible. 朋友类行导致error: specialization of 'template<class T> class Base' must appear at namespace scope template<T> friend class Base<T> ,并且成员变量container仍然不可访问。

A couple of issues: 几个问题:

Just as you don't put a <T> after the class name when defining a class template: 就像在定义类模板时不要在类名后放置<T>

template <class T> class X<T> { ... }; // WRONG
template <class T> class X { ... };    // RIGHT

you shouldn't put it after the class name when declaring a class template, whether in a forward declaration or friend declaration: 在声明类模板时,无论是在前向声明还是在朋友声明中,都不应将其放在类名之后:

template <class T> class X<T>; // WRONG
template <class T> class X;    // RIGHT - declares the template exists
template <class T> friend class X<T>; // WRONG
template <class T> friend class X;    // RIGHT - says all specializations of X are friends

(Unless you're creating a class template partial specialization. For example, if class template X is already declared, then template <class T> class X<T*> { ... }; defines a partial specialization that will be used instead of the primary template when the template argument is a pointer.) (除非您要创建类模板的部分专业化。例如,如果已经声明了类模板X ,则template <class T> class X<T*> { ... };定义了将被使用的部分专业化当template参数为指针时)。

And you have the friend declaration backwards: it needs to appear inside the class with the non-public member(s), and name the other class(es) which are allowed to use the members. 而且您的朋友声明向后:它需要与非公共成员一起出现在类中,并命名允许使用这些成员的其他类。 (If it worked the other way around, then any new class could gain access to any other class's private and protected members, without the permission of the owning class!) (如果以其他方式起作用,那么任何新类都可以在未经拥有类许可的情况下访问任何其他类的私有成员和受保护成员!)

So you would need: 因此,您需要:

template <class T> class Foo;

template<class T> class Base {
    template <class U> friend class Foo;
protected:
    T container;
};

The forward declaration of Foo is sometimes not needed, but I think it makes things clearer, and it can avoid gotchas when things start getting more complicated with namespaces, nested classes, etc. 有时不需要Foo的前向声明,但是我认为它使事情变得更清楚,并且当名称空间,嵌套类等开始变得更加复杂时,它可以避免麻烦。

只有Base可以说Foo是它的朋友。

template<typename T> friend class Foo; // every Foo<T> is a friend of Base

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM