博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
什么时候用引用,什么时候用指针的一个小例子
阅读量:5217 次
发布时间:2019-06-14

本文共 6311 字,大约阅读时间需要 21 分钟。

  之前也知道引用和指针的区别,但如果现在让我说他们两个有什么区别,我还是不太能全部说出来,(红色标记一下:引用和指针的异同有哪些?)之所以不能说出他两的区别,不是因为我记忆力不好,而是没有过实际代码的体验。在看Essential C++时,碰到下面的代码,感觉能够说明一些他两的用法。下面给出代码和书上的说明:

首先说明一下这里基类num_sequence和子类Fibonacci的目的。基类是一系列不同类型数列的抽象,比如斐波那契数列等等(这里仅以Fibonacci来举例说明子类)。先给出第一次设计基类和子类的代码:(第一次设计时基类不保存具体的数列Vector,只是一些子类抽象出来的函数)

1 基类

  1.1 num_sequence.h

num_sequence.h 
1 #pragma once  2 #include 
3 4 class num_sequence 5 {
6 public: 7 num_sequence(void); 8 virtual ~num_sequence(void); 9 virtual int elem( int pos ) const = 0; //返回子类pos位置的元素 10 virtual const char* what_am_i() const = 0; //返回子类的名字,比如Fibonacci 11 virtual std::ostream& print( std::ostream& os = std::cout ) const = 0; //console输出子类的成员变量信息 12 friend std::ostream& operator<<( std::ostream &os, const num_sequence &ns ); 13 static int max_elems() { return _max_elems; } //返回子类最多可以包含的元素个数 14 15 16 protected: 17 virtual void gen_elems( int pos ) const = 0; //给子类中添加元素 18 19 bool check_integrity( int pos ) const; //验证子类pos位置是否合法 20 21 const static int _max_elems = 1024; //子类数列最多可以包含的元素个数 22 };

  1.2 num_sequence.cpp

num_sequence.cpp
1 #include "StdAfx.h"  2 #include "num_sequence.h"  3  4 num_sequence::num_sequence(void)  5 {
6 } 7 8 num_sequence::~num_sequence(void) 9 {
10 } 11 12 13 bool num_sequence::check_integrity( int pos ) const 14 {
15 if ( pos <= 0 || pos > _max_elems ) 16 {
17 std::cerr << "!! invalid position: " << pos << " Cannot honor request\n" ; 18 return false; 19 } 20 return true; 21 } 22 23 std::ostream& operator<<( std::ostream &os, const num_sequence &ns ) 24 {
25 return ns.print( os ); 26 }

2 子类

  2.1 Fibonacci.h

Fibonacci.h
1 #pragma once  2 #include "num_sequence.h"  3 #include 
4 class Fibonacci : 5 public num_sequence 6 {
7 public: 8 Fibonacci( int len = 1, int beg_pos = 1 ); 9 ~Fibonacci(void); 10 11 virtual int elem( int pos ) const; 12 virtual const char* what_am_i() const { return "Fibonacci"; } 13 virtual std::ostream& print( std::ostream& os = std::cout ) const; 14 15 16 int length() const { return _length; } 17 int beg_pos() const { return _beg_pos; } 18 19 protected: 20 virtual void gen_elems( int pos ) const; 21 bool check_integrity( int pos, int size ) const; //必须声明 22 int _length; 23 int _beg_pos; 24 25 static std::vector
_elems; //保存数列的元素 26 };

  2.2 Fibonacci.cpp

Fibonacci.cpp
1 #include "StdAfx.h"  2 #include "Fibonacci.h"  3  4  5 std::vector
Fibonacci::_elems; 6 7 8 Fibonacci::Fibonacci( int len, int beg_pos ) : _length(len), _beg_pos(beg_pos) {} 9 10 Fibonacci::~Fibonacci(void) 11 {
12 } 13 14 int Fibonacci::elem( int pos ) const 15 {
16 if ( ! check_integrity(pos, _elems.size() ) ) 17 {
18 return 0; 19 } 20 if ( pos > _elems.size() ) 21 {
22 Fibonacci::gen_elems( pos );//一会测试一下改成执行期才决定选择哪个gen_elems 23 } 24 25 return _elems[ pos-1 ]; 26 } 27 28 29 void Fibonacci::gen_elems( int pos ) const 30 {
31 if ( _elems.empty() ) 32 {
33 _elems.push_back( 1 ); 34 std::cout << "gen_elems: " << 1 << std::endl; 35 _elems.push_back( 1 ); 36 std::cout << "gen_elems: " << 1 << std::endl; 37 } 38 39 if ( _elems.size() <= pos ) 40 {
41 int ix = _elems.size(); 42 int n_2 = _elems[ ix-2 ]; 43 int n_1 = _elems[ ix-1 ]; 44 45 for ( ; ix <= pos; ++ix ) 46 {
47 int elem = n_2 + n_1; 48 _elems.push_back( elem ); 49 std::cout << "gen_elems: " << elem << std::endl; 50 n_2 = n_1; 51 n_1 = elem; 52 } 53 } 54 } 55 56 std::ostream& Fibonacci::print( std::ostream& os ) const 57 {
58 int elem_pos = _beg_pos - 1; 59 int end_pos = elem_pos + _length; 60 61 if ( end_pos > _elems.size() ) 62 {
63 Fibonacci::gen_elems( end_pos );//这里和int Fibonacci::elem( int pos ) const中一样是 64 } //因为已经可以确定是执行Fibonacci的gen_elems函数,所以明确的告诉编译器,以便跳过虚拟函数机制 65 66 while ( elem_pos < end_pos ) 67 {
68 os << _elems[ elem_pos] << ' '; 69 ++elem_pos; 70 } 71 72 return os; 73 } 74 75 bool Fibonacci::check_integrity( int pos, int size ) const 76 {
77 if ( pos <= 0 || pos > _max_elems ) 78 {
79 std::cerr << "!! invalid position: " << pos << " Cannot honor request\n" ; 80 return false; 81 } 82 83 if ( pos > size ) 84 {
85 gen_elems( pos ); //通过虚拟机制调用 86 } 87 return true; 88 }

 

前面这些代码给出了第一次设计时候的思想,现在第二次设计时把一些子类都要用到的数据抽象到基类里,比如子类实际存储的vector等等。

1 class num_sequence  2 {
3 4 public: 5 virtual ~num_sequence() {} 6 virtual const char* what_am_i() const = 0; 7 int elem( int pos ) const; 8 ostream& print( ostream& os = cout ) const; 9 int length() const { return _length;} 10 int beg_pos() const { return _beg_pos; } 11 static int max_elems() { return 64; } 12 13 protected: 14 virtual void gen_elems( int pos ) const = 0; 15 bool check_integrity( int pos, int size ) const; 16 17 num_sequence( int len, int bp, vector
&re ) 18 : _length( len ), _beg_pos( bp ), _relems( re ) {} 19 int _length; 20 int _beg_pos; 21 vector
&_relems; 22 };

这里红色标记的地方是比较重要的地方:

  1、_relems声明为引用原因:reference永远无法代表空对象( null object ),pointer却可能是null。让它成为reference,我们就再也不必检查它是否为null了

  data members如果是reference,则必须在constructor的member initialization list中加以初始化一旦初始化后,就再也无法指向另一个对象如果data members是个pointer,就无此限制:我们可以再constructor内加以初始化,也可以先将它初始化为null,稍后再令它指向某个有效的内存地址

  2、num_sequence 的constructor为protected原因:num_sequence乃是一个抽象基类,我们无法为它定义任何对象。num_sequence扮演的角色是每个派生类对象的子对象(subobject)。基于这个理由,我们将基类的constructor声明为protected而非public

 

到这里本次文章的主要目的就结束了。但还有一个问题先记下来,方便以后回头查看:

  copy assignment operator 和 copy constructor的问题:Essential C++ P105 Triangular t3 = 8;会调用带有单一参数的constructor

  今天查了一下,大体上了解了为什么“Essential C++ P105 Triangular t3 = 8;会调用带有单一参数的constructor”。这里是因为之前尚未定义t3,如果之前已经定义过了,那么就是copy assignment operator (参考文献:

  

 

转载于:https://www.cnblogs.com/ziyoudefeng/archive/2012/03/20/2407197.html

你可能感兴趣的文章
php 表单提交方法
查看>>
AvalonDock的基本用法
查看>>
什么是Restful API
查看>>
关于Maven项目引入外部jar包的方式
查看>>
速卖通菜鸟云打印
查看>>
蛮牛第2季- Unity2d游戏开发经典教程
查看>>
数据库顺序查询
查看>>
wkhtmltopdf 参数介绍
查看>>
关于execel单元格中的数字变成文本(左上角带绿色三角形标志)的办法
查看>>
3.Python 文件的游标
查看>>
用户试用调查报告
查看>>
Leetcode Minimum Depth of Binary Tree
查看>>
介绍两种在RHEL 和 CentOS 系统上检查或列出已安装的安全更新的方法
查看>>
maven + eclipse + tomcat 实战JSP
查看>>
不使用存储过程获取Oracle自增序列(sequence)
查看>>
温故而知新 C# 运算符 表达式
查看>>
基于Android的上课助手的概况及第一周冲刺详情
查看>>
poj 2135(最小费用最大流)
查看>>
陶汝坤
查看>>
UnderWater+SDN论文之三
查看>>