本文试图解释c++ primer Screen 和 Window_Mgr的例子,为什么将两个类放在两个文件中无法编译?

将两个类写在同一个文件中,通过三个例子解释问题:

第一种写法问题:

编译到Screen时,由于Screen类使用到Window_Mgr的成员函数,虽然前面给出了Window_Mgr的声明,但此时还清楚Window_Mgr的完整定义,所以编译出错。

class Window_Mgr

class Screen

{

public:

friend Window_Mgr& Window_Mgr::relocate(Window_Mgr::index r, Window_Mgr::index c, Screen& s);

private:

int height;

int width;

}

class Window_Mgr

{

public:

typedef std::string::size_type index;

Window_Mgr& Window_Mgr::relocate(index r, index c, Screen& s)

{

s.height += r;

s.width += c;

return *this;

}

}

第二种写法问题在于:

编译到relocate时,由于Screen& s的实现使用到Screen的成员变量,虽然前面给出了Screen的声明,但此时还清楚Screen的完整定义,所以编译出错。

class Screen;

class Window_Mgr

{

public:

typedef std::string::size_type index;

Window_Mgr& Window_Mgr::relocate(index r, index c, Screen& s)

{

s.height += r;

s.width += c;

return *this;

}

}

class Screen

{

public:

friend Window_Mgr& Window_Mgr::relocate(Window_Mgr::index r, Window_Mgr::index c, Screen& s);

private:

int height;

int width;

}

第三种写法:

将Window_Mgr::relocate的实现移动到最后,由于编译类Window_Mgr时,并不需要Screen&s 的实现细节,问题得到解决

class Screen;

class Window_Mgr

{

public:

typedef std::string::size_type index;

Window_Mgr& Window_Mgr::relocate(index r, index c, Screen& s);

}

class Screen

{

public:

friend Window_Mgr& Window_Mgr::relocate(Window_Mgr::index r, Window_Mgr::index c, Screen& s);

private:

int height;

int width;

}

Window_Mgr& Window_Mgr::relocate(Window_Mgr::index r, Window_Mgr::index c, Screen& s)

{

s.height += r;

s.width += c;

return *this;

}

可见,这两个类如果编译成功需要严格的交替顺序

这也就解释了为什么放在两个文件中无法编译。

附录:

一开始的实现的不能编译的两个文件

实现分别如下:Window_Mgr.h

#ifndef WINDOW_MGR //为了避免两个文件嵌套

#define WINDOW_MGR

#include <string>

#include <Screen.h>

class Window_Mgr

{

public:

typedef std::string::size_type index;

Window_Mgr& Window_Mgr::relocate(index r, index c, Screen& s)

{

s.height += r;

s.width += c;

return *this;

}

}

#endif

Screen.h

#ifndef SCREEN

#define SCREEN

#include "Window_Mgr.h"

class Screen

{

public:

friend Window_Mgr& Window_Mgr::relocate(Window_Mgr::index r, Window_Mgr::index c, Screen& s);

private:

int height;

int width;

}

#endif

c++ primer,友元函数上的一个例子(By Sybase)的更多相关文章

  1. SpringBoot应用和PostgreSQL数据库部署到Kubernetes上的一个例子

    创建一个名为ads-app-service的服务: 上述Service的yaml文件里每个字段,在Kubernetes的API文档里有详细说明. https://kubernetes.io/docs/ ...

  2. 读书笔记 effective c++ Item 23 宁可使用非成员非友元函数函数也不使用成员函数

    1. 非成员非友元好还是成员函数好? 想象一个表示web浏览器的类.这样一个类提供了清除下载缓存,清除URL访问历史,从系统中移除所有cookies等接口: class WebBrowser { pu ...

  3. C++学习之路—运算符重载(二)运算符重载作为类的成员函数和友元函数

    (根据<C++程序设计>(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明) 对运算符重载的函数有两种处理方式:(1)把运算符 ...

  4. 关于C++中的friend友元函数的总结

    1.友元函数的简单介绍 1.1为什么要使用友元函数 在实现类之间数据共享时,减少系统开销,提高效率.如果类A中的函数要访问类B中的成员(例如:智能指针类的实现),那么类A中该函数要是类B的友元函数. ...

  5. matlab实现梯度下降法(Gradient Descent)的一个例子

    在此记录使用matlab作梯度下降法(GD)求函数极值的一个例子: 问题设定: 1. 我们有一个$n$个数据点,每个数据点是一个$d$维的向量,向量组成一个data矩阵$\mathbf{X}\in \ ...

  6. C++语言债券系列之十一——友元函数和拷贝构造函数

    1.好友功能 (1)友元函数类的普通功能外定义. 定义友元函数和相同的正常功能.在类必须声明的正常功能为好友. (2)友元函数不是一个成员函数. 你不能反对打电话.但直接调用:友元函数访问类的公共.p ...

  7. 【C++基础 05】友元函数和友元类

    友元是一种定义在类外部的普通函数或类,但它须要在类体内进行说明,为了与该类的成员函数加以差别,在说明时前面加以keywordfriend. 友元不是成员函数,可是它能够訪问类中的私有成员. 友元的作用 ...

  8. [C/C++] 友元函数和友元类

    A---友元函数: class Data{ public: ... friend int f(int &m);//友元函数 ... } 友元函数是可以直接访问类的私有成员的非成员函数.它是定义 ...

  9. 一个例子让你秒懂 Qt Creator 编译原理

    小北师兄作品 首发于微信公众号 小北师兄 微信 ID: ncuneupa 由于排版原因,文章可能读起来不太清晰,如果想看更好的排版,可以来我的公众号:小北师兄 大家好,我是你们的小北师兄,由于工作原因 ...

随机推荐

  1. LeetCode Lowest Common Ancestor of a Binary Search Tree (LCA最近公共祖先)

    题意: 给一棵二叉排序树,找p和q的LCA. 思路: 给的是BST(无相同节点),那么每个节点肯定大于左子树中的最大,小于右子树种的最小.根据这个特性,找LCA就简单多了. 分三种情况: (1)p和q ...

  2. Java [leetcode 37]Sudoku Solver

    题目描述: Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated ...

  3. 安装ejabberd2并配置MySQL为其数据库

    以前用过openfire做为服务器,但是openfire的集群支持不是很好,所以改用Ejabberd,由于它是用Erlang语言开发的,其并发率与分布式的功能都是很强悍的,在此我记录一下我的安装与配置 ...

  4. .Net 垃圾回收机制原理(二)

    英文原文:Jeffrey Richter 编译:赵玉开 链接http://www.cnblogs.com/yukaizhao/archive/2011/11/25/dot_net_GC_2.html ...

  5. Javascript 对输入框中的内容进行 “全选/反选”

    <</span>script> document.write("<</span>ul>"); for(var i=0;i<&l ...

  6. windows和linux间互传文件

    方法1:Xshell传输文件 用rz,sz命令在xshell传输文件 很好用,然后有时候想在windows和linux上传或下载某个文件,其实有个很简单的方法就是rz,sz 首先你的Ubuntu需要安 ...

  7. HDU 5618 Jam's problem again CDQ分治 BC ROUND 70

    题意:给你1e5个点(x,y,z),对于每一个点询问有多少个点(x1,y1,z1)满足x1<=x&&y1<=y&&z1<=z 分析:(官方题解奉上)很 ...

  8. FZU 2216 The Longest Straight 二分

    0可以表示任何1到m的数,求一个最长的连续上升序列长度 因为m的范围在10w,所以以每个节点为起点 进行二分,复杂度mlogm 思路:b[i]表示到 1 到 i 有几个数没有出现,二分的时候注意加等号 ...

  9. java Object类学习

    /* * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETA ...

  10. Makefile学习与进阶之Makefile.am和$$(M)的意思

    (1)makefile 中,出现$$(M) 是什么意思,发现还是看实际的Makefile长知识啊 在makefile中,会经常使用shell命令,也经常见到$var 和 $$var的情况,有什么区别呢 ...