什么时候用引用,什么时候用指针的一个小例子

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

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

1 基类

1.1 num_sequence.h
什么时候用引用,什么时候用指针的一个小例子什么时候用引用,什么时候用指针的一个小例子num_sequence.h

1 #pragma once 2 #include <iostream> 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; //返回子类的名字,比如Fibonacci11     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 ) const14 {15     if ( pos <= 0 || pos > _max_elems )16     {17         std::cerr << "!! invalid position: " << pos << " Cannot honor requestn" ;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 <vector> 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<int> _elems; //保存数列的元素26 };

2.2 Fibonacci.cpp
什么时候用引用,什么时候用指针的一个小例子什么时候用引用,什么时候用指针的一个小例子Fibonacci.cpp

1 #include "StdAfx.h" 2 #include "Fibonacci.h" 3  4  5 std::vector<int> 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 ) const15 {16     if ( ! check_integrity(pos, _elems.size() ) )17     {18         return 0;19     }20     if ( pos > _elems.size() )21     {22         Fibonacci::gen_elems( pos );//一会测试一下改成执行期才决定选择哪个gen_elems23     }24 25     return _elems[ pos-1 ];26 }27 28 29 void Fibonacci::gen_elems( int pos ) const30 {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 ) const57 {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 ) const76 {77     if ( pos <= 0 || pos > _max_elems )78     {79         std::cerr << "!! invalid position: " << pos << " Cannot honor requestn" ;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<int> &re )18         : _length( len ), _beg_pos( bp ), _relems( re ) {}19     int _length;20     int _beg_pos;21     vector<int> &_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 (参考文献:http://blog.sina.com.cn/s/blog_48d4d2df010002n9.html





原文链接: https://www.cnblogs.com/ziyoudefeng/archive/2012/03/20/2407197.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/44667

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月8日 下午9:18
下一篇 2023年2月8日 下午9:18

相关推荐