c – 将未定义的类作为好友,并在以后定义它

前端之家收集整理的这篇文章主要介绍了c – 将未定义的类作为好友,并在以后定义它前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
做一个不知名的朋友
template<typename T>
class List
{
protected:

    class a {
        int x;
        int y;
    private:
        friend class b;  // <------------ Why this is not an error? 
    };

    template <typename U > class b {  //If that is not a error this should be an error
        int z;
        U y;
    };

    public:
        List() {
            a* ptr = (a *)new unsigned char[sizeof(a)];
        }
};

int main() {
    List<int>  mylist;
}

请仔细阅读此链接,我的问题在代码中作为评论.
我想让另一堂课成为我班上的朋友.但在结交朋友时,这个班级并不知道.什么是允许它的C规则.
后来我以这样的方式定义该类,它与朋友声明不兼容.为什么不抛出错误.
谢谢

解决方法

是的,你的代码无效!这是一个有趣的展示模板如何以微妙的方式改变代码的含义.以下代码有效:
class List
{
public:
    class a {
        typedef int type;
        friend class b; // that's fine!
    };

    template <typename U > class b;
};

class b {
  List::a::type an_int; // allowed to access private member
};

标准说明在7.3.1.2/3

If a friend declaration in a non-local class first declares a class or function83) the friend class or function is a member of the innermost enclosing namespace.

什么时候是“第一次宣布的课程”?它也说那里

When looking for a prior declaration of a class or a function declared as a friend,and when the name of the friend class or function is neither a qualified name nor a template-id,scopes outside the innermost enclosing namespace scope are not considered.

“class b”的查找从7.1.5.3/2委派给3.4.4,后者又委托3.4 / 7的非限定名称查找.现在的所有问题是模板名称“b”是否在朋友声明类a中可见.如果不是,则找不到名称,并且friend声明将引用全局范围内的新声明的类. 3.3.6 / 1关于它的范围说

The potential scope of a name declared in a class consists not only of the declarative region following
the name’s declarator,but also of all function bodies,default arguments,and constructor ctor-
initializers in that class (including such things in nested classes).

忽略一些会使这个措辞不适用的迂腐点(这是一个缺陷但在该段的C 0x版本中修复,这也使这更容易阅读),这个列表不包括朋友声明作为一个区域模板名称可见的位置.

但是,该朋友是在类模板的成员类中声明的.实例化成员类时,将应用不同的查找 – 查找在类模板中声明的朋友名称!标准说

Friend classes or functions can be declared within a class template. When a template is instantiated,the
names of its friends are treated as if the specialization had been explicitly declared at its point of instantiation.

因此以下代码无效:

template<typename T>
class List
{
public:
    class a {
        typedef int type;
        friend class b; // that's fine!
    };

    template <typename U > class b;
};

// POI
List<int>::a x;

当这导致List< int> :: a被隐式实例化时,名称a被查找为“// POI”,好像会声明一个显式的特化.在这种情况下,模板List :: b已经被声明,并且此查找将命中它并发出错误,因为它是模板而不是非模板类.

猜你在找的C&C++相关文章