发现《深入理解C++11》中扩展的friend代码的错误
目前在总结现代C++的新特性,看了《深入理解C++11》这本书。
今天看到扩展的friend语法这一节,遇到了问题。本节电子版内容参见:https://book.2cto.com/201306/25354.html
未改良前的代码如代码清单2-21所示(在Linux下按照下面的编译指令能够通过),接着作者总结出了这种方法4点不好,给出了改良版代码(如代码清单2-22所示)。我要吐槽的是,反复试了好久,这改良版根本就不能够通过编译,感觉代码写的相当的鬼畜。
代码清单2-21
#include<iostream>
using namespace std;
// 为了方便测试,进行了危险的定义
#ifdef UNIT_TEST
#define private public
#endif
class Defender {
public:
void Defence(int x, int y){}
void Tackle(int x, int y){}
private:
int pos_x = 15;
int pos_y = 0;
int speed = 2;
int stamina = 120;
};
class Attacker {
public:
void Move(int x, int y){}
void SpeedUp(float ratio){}
private:
int pos_x = 0;
int pos_y = -30;
int speed = 3;
int stamina = 100;
};
#ifdef UNIT_TEST
class Validator {
public:
void Validate(int x, int y, Defender & d){}
void Validate(int x, int y, Attacker & a){}
};
int main() {
Defender d;
Attacker a;
a.Move(15, 30);
d.Defence(15, 30);
a.SpeedUp(1.5f);
d.Defence(15, 30);
Validator v;
v.Validate(7, 0, d);
v.Validate(1, -10, a);
return 0;
}
#endif
// 编译选项:g++ 2-9-3.cpp -std=c++11 -DUNIT_TEST
代码清单2-22
#include<iostream>
using namespace std;
template <typename T> class DefenderT {
public:
friend T;
void Defence(int x, int y){}
void Tackle(int x, int y){}
private:
int pos_x = 15;
int pos_y = 0;
int speed = 2;
int stamina = 120;
};
template <typename T> class AttackerT {
public:
friend T;
void Move(int x, int y){}
void SpeedUp(float ratio){}
private:
int pos_x = 0;
int pos_y = -30;
int speed = 3;
int stamina = 100;
};
using Defender = DefenderT<int>; // 普通的类定义,使用int做参数
using Attacker = AttackerT<int>;
#ifdef UNIT_TEST
class Validator {
public:
void Validate(int x, int y, DefenderTest & d){}
// 该行和下一行均报错:语法错误
void Validate(int x, int y, AttackerTest & a){}
//我在想这里的AttackerTest 是下面两行定义的,尝试把下面的两行提到前面错误变得更多了
};
using DefenderTest = DefenderT<Validator>; // 测试专用的定义,Validator类成为友元
using AttackerTest = AttackerT<Validator>;
int main() {
DefenderTest d;
AttackerTest a;
a.Move(15, 30);
d.Defence(15, 30);
a.SpeedUp(1.5f);
d.Defence(15, 30);
Validator v;
v.Validate(7, 0, d) ;
//此处和下一行均报错:函数不接受3个参数
v.Validate(1, -10, a);
return 0;
}
#endif
// 编译选项:g++ 2-9-4.cpp -std=c++11 -DUNIT_TEST
最后修改方法
using DefenderTest = DefenderT<Validator>; // 测试专用的定义,Validator类成为友元
using AttackerTest = AttackerT<Validator>;
把这两行提到
class Validator 之前,因为他的成员函数用到了这些定义
又因为 using DefenderTest = DefenderT<Validator>; 用到了 Valkidator 所以 要在这句话之前,前置声明一下 class Validator;
发现《深入理解C++11》中扩展的friend代码的错误的更多相关文章
- 理解ios 11中webview的视口
iOS 11在状态栏区域带来了一些新的,也许是不直观的行为,这对使用Apache Cordova或Ionic等工具的开发人员尤为重要.特别是,这种行为变化会影响任何基于Web的应用程序,这些应用程序在 ...
- 从linux0.11中起动部分代码看汇编调用c语言函数
上一篇分析了c语言的函数调用栈情况,知道了c语言的函数调用机制后,我们来看一下,linux0.11中起动部分的代码是如何从汇编跳入c语言函数的.在LINUX 0.11中的head.s文件中会看到如下一 ...
- JDK 11中的ZGC-一种可扩展的低延迟垃圾收集器
# 背景正如我们所知道的在JDK 11中即将迎来ZGC(The Z Garbage Collector),这是一个处于实验阶段的,可扩展的低延迟垃圾回收器.本文整合了外网几篇介绍ZGC的文章和代码. ...
- C++11 中值得关注的几大变化(网摘)
C++11 中值得关注的几大变化(详解) 原文出处:[陈皓 coolshell] 源文章来自前C++标准委员会的 Danny Kalev 的 The Biggest Changes in C++11 ...
- 深入理解Java虚拟机--中
深入理解Java虚拟机--中 第6章 类文件结构 6.2 无关性的基石 无关性的基石:有许多可以运行在各种不同平台上的虚拟机,这些虚拟机都可以载入和执行同一种平台无关的字节码(ByteCode),从而 ...
- 深入理解C++11【5】
[深入理解C++11[5]] 1.原子操作与C++11原子类型 C++98 中的原子操作.mutex.pthread: #include<pthread.h> #include <i ...
- 深入理解C++11【4】
[深入理解C++11[4]] 1.基于范围的 for 循环 C++98 中需要告诉编译器循环体界面范围.如for,或stl 中的for_each: int main() { ] = { , , , , ...
- 深入理解C++11【3】
[深入理解C++11[3]] 1.POD类型 Plain Old Data. Plain 表示 了POD是个普通的类型.C++11将POD划分为两个基本概念的合集: 1)平凡的(trivial) 2) ...
- 深入理解C++11
[深入理解C++11] 1.很多 现实 的 编译器 都 支持 C99 标准 中的__ func__ 预定 义 标识符 功能, 其 基本 功能 就是 返回 所在 函数 的 名字. 编译器 会 隐式 地 ...
随机推荐
- 关于Android开发中使用的XML
1.布局 FrameLayout: 以堆叠方式显示一个或多个子视图. GridLayout: 将子视图按行和列排列. LinearLayout: 将所有子视图排列成一行或一列. RelativeLay ...
- [sql异常]SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的
//执行远程数据库表查询 SELECT * FROM OPENDATASOURCE('SQLOLEDB', 'Data Source=数据库地址;User ID=sa;password=sa' ).n ...
- Building Boost for Android with error “cannot find -lrt”
编辑tools/build/src/tools/gcc.jam rule setup-threading ( targets * : sources * : properties * ){ local ...
- rsyslog local0-local7的用法
很多时候我们需要将一个服务的日志文件导向一个指定的文件,这个时候可以设置log-facility 如在dhcpd.conf中配置 1 : update log-facility in the dhcp ...
- MVC验证
前言 MVC自己的验证机制,通过一个案例记录学习的成果. 首先,model代码如下: public class Students { [Display(Name = "I ...
- 如何玩facebook app上的H5游戏
一.下载facebook app facebook链接 二.下载vpn 国内是访问不了的,必须vpn 因为vpn被封了厉害 我随便百度了个狸猫加速器,没付费,时断时续... 没有推荐的vpn,哪位大佬 ...
- iOS 循环引用 委托 (实例说明)
如何避免循环引用造成的内存泄漏呢: 以delegate模式为例(viewcontroller和view之间就是代理模式,viewcontroller有view的使用权,viewcontroller同时 ...
- 在pycharm中运行nose测试框架
之前一直在pydev上或命令行上运行nosetests. pycharm上如果运行nosetests,在看了管网后,总结果如下: 全新的pycharm: 填加完成后,打开你要的脚本,运行,即可以以no ...
- 通过Adb 查看当前正在运行的Activity.
extends:http://www.cnblogs.com/tt_mc/p/4269833.html adb shell dumpsys activity activities | sed -En ...
- Xcode - xcode-select: error: tool 'xcodebuild' requires Xcode报错解决方案
用mac 自带的终端执行的命令,安装安装Vapor和toolbox 安装指令: macdeMacBook-Pro:~ mac$ curl -sL check.vapor.sh| bash 结果报这个错 ...