C++ 类 超细节攻略

C++坑了我不少的时间,这回把类算是弄得明白一些,在此记录一下。内容非常繁杂,请做好心理准备。

我会以代码的形式来表达,并且附上一些解释。

① 编译器分两步处理类:

  • 编译成员的声明
  • 直到类全部可见后才编译成员函数体

② C++ 中class与struct的区别?

  • C++中唯一区别就是默认的访问权限,struct是public,class是private
  • C#中区别很大,详情百度

③ .h文件 (注意:是struct)

 1 struct Sales_data
 2 {
 3     // 定义友元函数让其可以访问类的非公有成员
 4     friend Sales_data add(const Sales_data &, const Sales_data &);
 5
 6 public:
 7     // Sales_data() = default;
 8     // 构造函数,不能声明const
 9     // 等同于编译器自动合成的构造函数
10     // 在(= default)在类的内部,则默认构造函数是内联的,如在类的外部,则该成员默认不是内联的
11
12     Sales_data() : Sales_data("", 0, 0) {}
13     // 委托构造函数:使用它所属的类的其他构造函数执行自己的初始化过程
14
15     /* explicit 抑制构造函数的隐式转换,只允许出现的类内*/ Sales_data(const string &s) : bookNo(s) {}
16     Sales_data(const string &s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(p*n) {}
17
18     string isbn() const {return bookNo;}
19     // 等价于
20     // string isbn(const Sales_data *const this//隐式//) {return this->bookNo;}
21     // 意思就是this是一个指向常量的常量指针。不能修改this中的内容。
22
23     Sales_data& combine (const Sales_data&);
24
25
26 private:
27     double avg_price() const;
28     string bookNo;
29     unsigned units_sold = 0;
30     double revenue = 0.0;
31 };

④ .cpp文件

 1 Sales_data& Sales_data::combine(const Sales_data &rhs)
 2 {
 3     units_sold += this->units_sold;
 4     revenue += rhs.revenue;
 5     return *this; // 返回指针引用
 6 }
 7
 8 double Sales_data::avg_price() const
 9 {
10     if (units_sold)
11         return revenue / units_sold;
12     else
13         return 0;
14 }
15
16 Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
17 {
18     Sales_data sum = lhs;
19     sum.combine(rhs);
20     return sum;
21 }

⑤ main函数

 1 int main()
 2 {
 3     Sales_data total;
 4     total.isbn();
 5     // 等价于
 6     // total.isbn(&total);
 7     // 调用时候传入了total对象的地址
 8
 9     const Sales_data sales_data;
10     // 直到构造函数完成初始化过程,对象才能真正取得其“常量”属性
11     // 构造函数在const对象的构造过程中可以向其写值
12
13     total.combine(sales_data).isbn();
14     // 非引用传参调用拷贝构造(此函数是引用参数,则没有拷贝构造)
15     // 返回一个类对象调用拷贝构造
16
17     total = sales_data;
18     // 赋值操作
19
20     Sales_data obj();  // 声明了一个函数
21     Sales_data obj2;   // 声明了一个对象
22
23     Sales_data item;
24     string null_book = "9-999-99999-9";
25     item.combine(null_book); // 将null-book隐式转换成Sales_data对象
26     //item.combine("9-999-99999-9"); // 错误,只允许一步转换,不能将字符转换成string再转换成对象
27
28     // this 是一个常量指针
29     return 0;
30 }

⑥ class Screen 与⑦的类示例友元类

 1 class Screen
 2 {
 3 public:
 4     typedef std::string::size_type pos;
 5     // 等同于
 6     // using pos = std::string::size_type;
 7     // 必须先定义后使用
 8
 9     friend class Window_mgr;
10     // Window_mgr的成员可以访问Screen类的私有成员
11
12     // friend void Window_mgr::clear(ScreenIndex);
13     // 让函数作为友元
14
15     Screen() = default;
16     Screen(pos ht, pos wd, char c) : height(ht), width(wd), contents(ht * wd, c) {}
17
18     char get() const // 隐式内联
19     {
20         return contents[cursor];
21     }
22
23     inline char get(pos ht, pos wd) const; // 显式内联
24
25     Screen &move(pos r, pos c); // 可以在类的外部声明时定义成内联函数
26
27     Screen &set(char);
28
29     Screen &set(pos, pos, char);
30
31     const Screen &display() const;
32
33     void dummy_fcn(pos height)
34     {
35         cursor = width * height; // 用的是参数height
36         cursor = width * this->height; // 用的是成员height
37         // cursor = width * ::height; // 用的是全局的height
38     }
39
40 private:
41     pos cursor = 0;
42     pos height = 0, width = 0;
43     std::string contents;
44     mutable size_t access_ctr = 0; // mutable(可变数据成员),在const成员函数中也可以改变值
45 };
46
47 char Screen::get(pos ht, pos wd) const
48 {
49     pos row = ht * width;
50     ++access_ctr; // 正确
51     // ++cursor; 错误
52     return contents[row + wd];
53 }
54
55 inline Screen &Screen::move(pos r, pos c) // 声明的时候声明inline函数
56 {
57     pos row = r * width;
58     cursor = row + c;
59     return *this;
60 }
61
62 inline Screen &Screen::set(char c)
63 {
64     contents[cursor] = c;
65     return *this;
66     // 返回对象的引用,说明返回的是对象本身,而不是对象的拷贝
67     // 如果返回类型为Screen,则返回的是对象的拷贝
68 }
69
70 inline Screen &Screen::set(pos r, pos col, char ch)
71 {
72     contents[r * width + col] = ch;
73     return *this;
74 }
75
76 inline const Screen &Screen::display() const
77 {
78     return *this; // const成员函数返回其指针,则为常量指针
79 }

⑦ class Window_mgr

 1 class Window_mgr
 2 {
 3 public:
 4     using ScreenIndex = std::vector<Screen>::size_type;
 5
 6     void Clear(ScreenIndex);
 7
 8     ScreenIndex addScreen(const Screen&);
 9
10 private:
11     std::vector<Screen> screens{ Screen(24, 80, ‘ ‘) };
12     // 类内初始值,必须以符号=或{}表示
13 };
14
15 void Window_mgr::Clear(ScreenIndex index) // void 为作用域之外,从Window_mgr开始为作用域内
16 {
17     Screen &s = screens[index];
18     s.contents = std::string(s.height * s.width, ‘ ‘);
19     // 因Window_mgr是Screen的友元类,所以可以访问Screen的私有成员height、width和contents
20     // 注:友元关系不存在传递性,如果Window_mgr有友元类,其友元类没有访问Screen的权利
21 }
22
23 Window_mgr::ScreenIndex Window_mgr::addScreen(const Screen &s) // 返回类型在类作用域中定义,则必须用类名
24 {
25     screens.push_back(s);
26     return screens.size() - 1;
27 }

如有补充欢迎留言~

原文地址:https://www.cnblogs.com/SHOR/p/8448080.html

时间: 2025-01-18 05:00:15

C++ 类 超细节攻略的相关文章

黑客榜中榜,超详细攻略!小白整理

黑客榜中榜第一期攻略 本人萌新小白一个,尽量把步骤都详细的整理出来,供新手参考. 先是第一期第一关 上图..... 这个是在未知的情况下要求通过各种方法获取到密码,然后登陆! 我使用的是火狐浏览器,使用F12快捷键,可以看到网页HTML源代码,分析源代码! 很多我都看不懂....... 分析一下能看懂的: if判断试 首先定义了一个全局变量"X"(至于"X"等于啥玩意我就不知道了,回头再研究) 下面就是判断 "X"是否等于 "go   

MyEclipse自动生成hibernate实体类和配置文件攻略

步骤1:找到导航栏里面的window--showView然后输入db brower,打开数据库浏览窗口步骤2:在数据库浏览窗口里只有一个Myeclipse自带的数据库,该数据没有用,我们在空白的地方右键新建一个数据库填写数据库信息,包括连接方式,用户名,密码,和jdbc的配置一样,注意将oracle的jar包导进来 步骤3:数据库连接已经出现,我们可以连接上数据库了 步骤4:这时候我们回过头,新建一个java或javaEE项目,名字随便取,然后右键该项目,选择Myeclipse---add hi

迭代器超详细攻略

写的很墨迹,将就看. 首先 理解 for 循环 for i in [1,2,3,4] print i 这个是正常 如果 for 循环一个 1234 会报错,因为 int 不是一个 iterable 类型 iterable :  字典里的意思是 可迭代的, 可重复的 可迭代的对象: 字符串str          列表 list      元组 tuple      字典 dict    集合set #证明是否可迭代from collections import Iterable l = [12,

GitHub超详细图文攻略

GitHub超详细图文攻略 - Git客户端下载安装 GitHub提交修改源码工作流程 Git分支 标签 过滤 Git版本工作流 分类: 转载2014-03-25 21:10 1692人阅读 评论(0) 收藏 举报 GitHubbranchAndroidmsysgit代码 目录(?)[+] 最近听同事说他都在使用GitHub,GitHub是程序员的社区,在里面可以学到很多书上学不到的东西,所以最近在准备入手这方面的知识去尝试学习,正好碰到这么详细完整的文章,就转载了,希望对自己和大家有帮助.  

手游类App安全防破解攻略-先来做个漏洞分析吧

2014年6月初,爱加密高调推出免费自动化App安全检测平台,这是国内首家自动化智能App安全检测平台,也是爱加密推出的一个重磅产品,甚至在目前整个互联网行业,包括移动互联网行业还没有这样智能完善的服务平台出现,其应用方向和行业前景相当乐观.       只需一键,专业简单,让风险漏洞无处遁形 目前来说,移动应用开发者众多,他们可能不知道自己的应用是否安全,是否容易被他人破解进行二次打包.出于此类需求,爱加密推出爱加密免费漏洞分析平台.该平台集成了目前黑客最常用的各种破解方法与思路,模拟黑客攻击

备战软考(4) 软考下午题攻略

软考的全称是全国计算机技术与软件专业技术资格(水平)考试,而我们今天讨论的是其中的中级职称的一个科目----软件设计师.这个级别的考试主要分为两大块基础知识和应用技术,分别在考试当天的上午和下午进行测试. 对于基础知识这块,因为考查的知识面很广,也很细,个人而言无法找到一个行之有效的办法能让你迅速的提高上午题的成绩,因此就不在这里总结了,我们要做的就是看书,做题,再看书,再做题,然后接着看书,在看书与做题的反复中,一个一个的消灭自己的知识盲点和填补知识漏洞,这样慢慢的也许会有提升,但不要企图短时

LINUX SHELL脚本攻略笔记[速查]

Linux Shell脚本攻略笔记[速查] 资源 shell script run shell script echo printf 环境变量和变量 pgrep shell数学运算 命令状态 文件描述符和重定向 cat 数组和关联数组 alias date 调试脚本 函数和参数 管道 读取命令输出 read 字段分隔符和迭代器 循环 比较和测试 find xargs tr md5sum sha1sum 对目录进行校验 sort uniq tempfile split bash变量匹配切分 exp

完美商业计划书全攻略

http://mp.weixin.qq.com/s?__biz=MjM5NDk5MTA0MQ==&mid=400159971&idx=1&sn=5451cc4bc3d62cc1f6e1676a2961131e&scene=0&key=b410d3164f5f798e3bffbefe9277f497e3823645496c804d2bddffe4f115dd8d79a628ca93efd4b44d83eb358732bdb5&ascene=0&uin=

JQuery攻略(四)事件

jQuery事件处理,鼠标的单击,双击,悬停,键盘按键,文本动画..... 此章节有 1.1被点击的按钮查找 1.2事件的自动触发 1.3点击之后禁用按钮 1.4鼠标事件 1.5焦点事件 1.6CSS的操作 1.7元素创建 1.8动画隐藏和展示 1.9效果 1.10键盘输入控制 1.11防止事件冒泡 小结 1.1被点击的按钮查找 一个页面上有很多按钮,对应不同的功能,一个按钮对应一个事件,说到底就是给每个按钮绑定一个事件. <html xmlns="http://www.w3.org/19