使一个未定义的类成为朋友,然后再对其进行定义 [英] Making an undefined class as friend, and defining it later

查看:89
本文介绍了使一个未定义的类成为朋友,然后再对其进行定义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

交一个未知的朋友

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 ++规则是什么. 稍后,我将以与朋友声明不兼容的方式定义该类.为什么不抛出错误. 谢谢

Please go through this link, I have my questions as comments in the code. I am trying to make another class a friend of my class. But that class is not know at the time of making friend. What is the C++ rule that allows for it. Later I am defining that class in such a way that, it is incompatible with the friend declaration. Why is that not throwing an error. Thanks

推荐答案

是的,您的代码是无效!这是有关模板如何以微妙的方式更改代码含义的有趣展示.以下代码是有效的:

Yes your code is invalid! This is an interesting show of how templates can change meaning of code in subtle ways. The following code is valid:

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

Standard says at 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 is it a "first declared class"? It says that too there

在寻找被声明为好友的类或函数的先前声明时,并且当好友类或函数的名称既不是限定名也不是template-id时,最内层的命名空间范围之外的范围就不会考虑过的.

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.

类b"的查找从7.1.5.3/2委派到3.4.4,这又委派给3.4/7的不合格名称查找.现在所有的问题是在朋友声明类a中模板名称"b"是否可见.如果未找到,则找不到名称,并且Friend声明将引用全局范围内的新声明的类. 3.3.6/1关于它的范围说

The lookup for "class b" is delegated from 7.1.5.3/2 to 3.4.4 which in turn delegates to unqualified name lookup at 3.4/7. All the question now is whether the template-name "b" is visible in the friend declaration class a. If it isn't, the name is not found and the friend declaration will refer to a new declared class at global scope. 3.3.6/1 about the scope of it says

在类中声明的名称的潜在范围不仅由后面的声明性区域组成 名称的声明符,还包括所有函数体,默认参数和构造函数ctor- 该类中的初始化程序(包括嵌套类中的此类内容).

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版本中得到修复,这也使此内容更易于阅读),该列表不包括朋友声明作为该模板名称可见的区域.

Ignoring a few pedantic points that would make this wording not apply to here (which were a defect but are fixed in the C++0x version of that paragraph which also makes this easier to read), this list does not include the friend declaration as an area where that template name is visible.

但是,朋友是在类模板的成员类中声明的.当实例化成员类时,将应用 different 查找-查找在类模板中声明的朋友姓名!标准说

However, the friend was declared in a member class of a class template. When the member class is instantiated different lookup applies - the lookup for friend names declared in a class template! The Standard says

朋友类或函数可以在类模板中声明.实例化模板时, 它的朋友的名字将被视为该专门化已在其实例化点被明确声明.

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已经被声明,并且此查找将命中它并发出错误,因为它是模板而不是非模板类.

When that causes List<int>::a to be implicitly instantiated, the name a is looked up at "// POI" as if there would have been an explicit specialization declared. In that case, the template List::b has already been declared, and this lookup will hit it and emit an error because it's a template and not a non-template class.

这篇关于使一个未定义的类成为朋友,然后再对其进行定义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆