0

假设我必须遵循层次结构:

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 */
    }
};

现在我想要一个独立的类(不是从 Base 派生的),它可以Base<T>::container直接从 Base 或任何派生类访问。我阅读了有关模板朋友类的信息,它似乎是我问题的解决方案,但我还无法弄清楚语法。我正在寻找类似的东西:

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()

朋友类行导致一个error: specialization of ‘template<class T> class Base’ must appear at namespace scope template<T> friend class Base<T>并且成员变量container仍然无法访问。

4

2 回答 2

1

几个问题:

就像你<T>在定义类模板时没有在类名后面加 a 一样:

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

声明类模板时,无论是在前向声明还是在友元声明中,都不应将其放在类名之后:

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

(除非您正在创建类模板部分特化。例如,如果类模板X已声明,则template <class T> class X<T*> { ... };定义一个部分特化,当模板参数是指针时,将使用该部分特化代替主模板。)

并且你有向后的朋友声明:它需要出现在具有非公共成员的类中,并命名允许使用成员的其他类。(如果它反过来工作,那么任何新类都可以访问任何其他类的私有和受保护成员,而无需拥有类的许可!)

所以你需要:

template <class T> class Foo;

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

有时不需要前向声明Foo,但我认为它使事情变得更清晰,并且当命名空间、嵌套类等变得更加复杂时,它可以避免出现问题。

于 2018-12-15T01:22:03.247 回答
0

只能BaseFoo是它的朋友。

template<typename T> friend class Foo; // every Foo<T> is a friend of Base
于 2018-12-15T01:22:21.217 回答