王道短期班c++ day06

this指针

this指针代表的就是当前对象本身,是作为成员函数的第一个隐含的参数,编译器在编译时会自动加上,不需要程序员手动提供

this指针不可以被修改

this指针作为隐含参数

对象的复制

赋值运算符函数形式:类名& operator=(const 类名&);

     Point & operator=(const Point & rhs)
     {
         _ix=rhs._ix;
         _iy=rhs._iy;
         cout<<"Point & operator=(const Point &)"<<endl;                              
     }

1.返回值可以不返回引用吗?

可以,但是返回对象时相当于做了一次复制操作,增加了系统开销

  1 #include <iostream>
  2 using std::cout;
  3 using std::endl;
  4 using std::cin;
  5 
  6 class Point
  7 {
  8 public:
  9     Point()=default;
 10 
 11     Point(int ix,int iy)
 12     :_ix(ix)
 13     ,_iy(iy)
 14     {
 15         /* cout<<"Point()"<<endl; */
 16     }
 17 
 18     Point(const Point & rhs)
 19     :_ix(rhs._ix)
 20     ,_iy(rhs._iy)
 21     {
 22         cout<<"拷贝构造函数调用"<<endl;
 23     }
 24 
 25     Point & operator=(const Point & rhs)
 26     {
 27         /* this=1000;//error */
 28         _ix=rhs._ix;
 29         _iy=rhs._iy;
 30         cout<<"Point & operator=(const Point &)"<<endl;
 31         return * this;
 32     }
 33 
 34     void printInfo(){
 35         cout<<"("<<_ix
 36             <<","<<_iy
 37             <<")"<<endl;                                                               
 38     }
 39 
 40 
 41     ~Point()
 42     {
 43         /* cout<<"析构函数调用"<<endl; */
 44     }
 45 
 46 private:
 47     int _ix;
 48     int _iy;
 49 };
 50 
 51 void test0(){
 52     Point pt1(1,1);
 53     Point pt2(2,2);
 54     pt2=pt1;
 55     pt1.printInfo();//==pt1.printInfo(&pt1)
 56    // ==Point::prinInfo(&pt1)
 57 }
 58 
 59 int main()
 60 {
 61     test0();
 62     return 0;
 63 }

增加引用

不加引用

2.返回值可以是void吗?

不可以

编译结果

赋值函数报错的情况

  1 #include <iostream>
  2 #include <string.h>
  3 using std::cout;
  4 using std::endl;
  5 
  6 class Computer
  7 {
  8 public:
  9     Computer()=default;
 10     Computer(const char * brand,float price)
 11     :_brand(new char[strlen(brand)+1])
 12     ,_price(price)
 13     {
 14         cout<<"构造函数调用"<<endl;
 15     }
 16     //拷贝构造函数 深拷贝
 17     Computer(const Computer &rhs)
 18     :_brand(new char[strlen(rhs._brand)+1]())
 19     ,_price(rhs._price)
 20     {
 21         strcpy(_brand,rhs._brand);
 22         cout<<"拷贝构造函数调用,深拷贝"<<endl;
 23     }
 24     ~Computer(){
 25         if(_brand){
 26             delete [] _brand;
 27             _brand=nullptr;
 28 
 29          }
 30         cout<<"~Computer()"<<endl;
 31     }                                                
 32 
 33     Computer & operator=(const Computer & rhs)
 34     {
 35         _brand=rhs._brand;
 36         _price=rhs._price;
 37         cout<<"Computer & operator=(const Computer& rhs)"<<endl;
 38         return *this;
 39     }
 40 private:
 41     char *_brand;
 42     float _price;
 43 };
 44 void test0()
 45 {
 46     Computer c1("macbook",9999);
 47     Computer c2("华为matebook",8888);
 48     c2=c1;
 49 }
 50 
 51 int main()
 52 {
 53     test0();
 54     return 0;
 55 }

 运行结果

原因:与拷贝构造哪里同理,两个指针指向了同一块堆空间,调用析构函数的时候,对同一个堆空间释放了两次

解决策略

1回收左操作数申请的空间,2进行深拷贝

运行结果

三合成原则

当类中需要显式提供析构函数、拷贝构造函数、赋值运算符函数中的其中一个时,另外两个也需要提供

特殊的数据成员的初始化

1.const数据成员 2.引用数据成员 3.对象数据成员 4.静态数据成员,前三者的初始化都必须要放入初始化列表中进行

const数据成员

放入初始化列表

引用数据成员

对象成员

    1 #include <iostream>
    2 using std::cout;
    3 using std::endl;
    4 using std::cin;
    5 
    6 class Point
    7 {
    8 public:
✹   9     Point()=default;
   10 
   11     Point(int ix,int iy)
   12     :_ix(ix)
   13     ,_iy(iy)
✹  14     ,_ref(iy)
   15     {
   16         /* _ref=iy; */
   17         /* cout<<"Point()"<<endl; */
   18     }
   19 
   20     Point & operator=(const Point & rhs)
   21     {
   22         /* this=1000;//error */
   23         _ix=rhs._ix;
   24         _iy=rhs._iy;
   25         cout<<"Point & operator=(const Point &)"<<endl;
✹  26     }
   27 
   28     void printInfo(){
   29         cout<<"("<<_ix
   30             <<","<<_iy                                                               
   31             <<")"<<endl;
   32     }
   33 
   34     ~Point()
   35     {
   36         /* cout<<"析构函数调用"<<endl; */
   37     }
   39 private:
   40     int _ix;
   41     int _iy;
   42     int &_ref;//引用数据成员
   43 };                                                                                   
   44 
   45 class Line
   46 {
   47 public:
   48     Line(int x1,int y1,int x2,int y2)
   49     :_p1(x1,y1)
   50     ,_p2(x2,y2)
   51     {
   52         cout<<"Line()"<<endl;
   53     }
   54     void printLine(){
   55       _p1.printInfo();
   56       cout<<endl;
   57       _p2.printInfo();
   58     }
   59 
   60 private:
   61     Point _p1;
   62     Point _p2;
   63 };
   64 
   65 void test1()
   66 {
   67     Line l1(1,2,3,4);
   68     l1.printLine();
   69 }
   70 
   71 Point test2()
   72 {
   73     Point pt1(1,1);
   74     return pt1;
   75 }
   76 
   77 int main()
   78 {
   79     test1();
   80     return 0;
   81 }

运行结果

静态数据成员

static 全局静态区,在类中定义的static数据成员,也是放在全局静态区的=》不会占据类或者对象的存储空间,静态数据成员会被整个类创建的对象所共享

  1 #include <iostream>
  2 #include <string.h>
  3 using std::cout;
  4 using std::endl;
  5 
  6 class Computer
  7 {
  8 public:
  9     Computer()=default;
 10     Computer(const char * brand,float price)
 11     :_brand(new char[strlen(brand)+1])
 12     ,_price(price)
 13     {
 14         total_price+=_price;
 15         cout<<"构造函数调用"<<endl;
 16     }
 17     //拷贝构造函数 深拷贝
 18     Computer(const Computer &rhs)
 19     :_brand(new char[strlen(rhs._brand)+1]())
 20     ,_price(rhs._price)
 21     {
 22         strcpy(_brand,rhs._brand);
 23         cout<<"拷贝构造函数调用,深拷贝"<<endl;
 24     }
 25 
 26     ~Computer(){
 27         if(_brand){
 28             delete [] _brand;
 29             _brand=nullptr;
 30 
 31          }
 32         cout<<"~Computer()"<<endl;
 33     }
 34 
 35     Computer & operator=(const Computer & rhs)
 36     {
 37         if(this!=&rhs){                                                                
 38             delete [] this->_brand;
 39             _brand=new char[strlen(rhs._brand)+1]();
 40             strcpy(_brand,rhs._brand);
 41             this->_price=rhs._price;
 42         }
 43 
 44         cout<<"Computer & operator=(const Computer& rhs)"<<endl;
 45         return *this;
 46     }
 47 
 48     void printinfo()
 49     {
 50      cout<<"总价格为:"<<total_price
 51          <<"电脑品牌:"<<this->_brand
 52          <<"价格为:"<<this->_price<<endl;
 53     }
 54 private:
 55     char *_brand;
 56     float _price;
 57     static float total_price;
 58 };
 59 
 60 float Computer::total_price=0;
 61 
 62 void test0()
 63 {
 64     Computer c1("macbook",9999);
 65     Computer c2("华为matebook",8888);
 66     c2=c1;
 67     c2.printinfo();
 68 }
 69 
 70 int main()
 71 {
 72     test0();
 73     return 0;
 74 }

运行结果,说明静态变量存在全局静态区

静态成员函数

在一个普通的成员函数前面加上static关键字,该函数就成为static成员函数。

静态成员函数没有隐含的this指针,不能访问非静态的数据成员和成员函数,只能访问静态的数据成员和成员函数,可以直接通过类名调用, 不需要对象的存在。

如图,静态成员函数没有隐含的this指针

不能访问非静态得数据成员和成员函数

可以通过类名调用,不需要对象的存在

运行结果

const成员函数

const关键字放在成员函数的形参列表之后,就称为const成员函数

注意:只要成员函数不会对数据成员进行修改,都应该将其设计为const成员函数,const成员函数只能读取数据成员,不能修改数据成员

const关键字的作用是:修改了this指针的形式,让其变成了双重限定的this指针

空指针的使用情况

  1 #include <iostream>
  2 using std::cout;
  3 using std::endl;
  4 
  5 class NullPointer
  6 {
  7 public:
  8     void test1(){
  9         cout<<"test1()"<<endl;
 10     }
 11     void test2(int x){
 12         cout<<"test2() x"<<x<<endl;
 13     }
 14     void test3(){
 15         cout<<"test3()"<<this->_ix<<endl;
 16     }
 17     static void test4(){
 18         cout<<"test4()"<<endl;
 19     }
 20 
 21 private:
 22     int _ix;
 23 
 24 };
 25 
 26 void test0()
 27 {
 28     NullPointer* np=nullptr;
 29     np->test1();
 30     np->test2(1);
 31     np->test4();
 32     np->test3();
 33 }
 34 
 35 int main()
 36 {
 37     test0();                                                                           
 38     return 0;
 39 }

运行结果

test3发生段错误的原因,只有test3函数内部需要访问数据成员_ix,而传递过去的是一个空指针,没有对象可以使用,所以报错。

单例模式

单例模式是23种设计模式中最简单最常见的一种,要求通过一个类只能创建一个对象。

单例模式的应用场景

1.单例模式可以用来替换全局变量

2.配置文件中的信息可以存储在单例对象中

3.网页库,倒排索引库都可以使用单例模式

实现单例模式的具体步骤

1.在类中定义一个静态的指向本类型的指针

2.将构造函数私有化

3.在public区域定义一个静态成员函数

单例模式实例

  1 #include <iostream>
  2 using std::cout;
  3 using std::endl;
  4 
  5 class Singleton
  6 {
  7 public:
  8     static Singleton * getInstance()
  9     {
 10         if(_p==nullptr)
 11         {
 12             _p=new Singleton;
 13         }
 14         return _p;
 15     }
 16     void init(int ix,int iy)
 17     {
 18         _ix=ix;
 19         _iy=iy;
 20     }
 21     void destroySingleton()
 22     {
 23         if(_p!=nullptr)
 24         {
 25             delete _p;
 26             _p=nullptr;
 27         }
 28     }
 29 
 30 private:
 31     Singleton(int ix=0,int iy=0)
 32     :_ix(ix)
 33     ,_iy(iy)
 34     {
 35         cout<<"Singleton()"<<endl;
 36     }
 37     ~Singleton()                                                                                        
 38     {
 39         cout<<"~Singleton()"<<endl;
 40     }
 41 
 42 private:
 43     int _ix;
 44     int _iy;
 45     static Singleton *_p;
 46 };
 47 
 48 Singleton* Singleton::_p=nullptr;
 49 
 50 void test0()
 51 {
 52     Singleton *s1=Singleton::getInstance();
 53     Singleton *s2=Singleton::getInstance();
 54     cout<<"&s1:"<<s1<<endl;
 55     cout<<"&s:2"<<s2<<endl;
 56    // Singleton s1;//error 使用单例模式只能创建一个对象 
 57    s2->destroySingleton();
 58 }
 59 
 60 
 61 int main()
 62 {
 63     test0();
 64     return 0;
 65 }

运行结果也表明只能创建一个对象

  • 25
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
王道数据结构C是一种基于C语言的数据结构实现的教材或参考书籍。该教材根据数据结构的原理与应用,详细介绍了常见的数据结构和算法,并给出了它们的C语言实现。 在实现王道数据结构C时,我们可以通过以下几个步骤来进行: 1. 理解数据结构的原理和特性:首先,我们需要深入理解所学习的数据结构的基本原理和特性,包括线性表、链表、栈、队列、树、图等。熟悉它们的操作规则以及适用的场景。 2. 设计算法和数据结构:其次,针对每个数据结构,我们需要设计相应的算法和数据结构,以满足各种操作和需求。对于线性表,我们可以选择使用顺序表或链表来实现,对于树结构,可以选择二叉树或多叉树等等。 3. 编写C语言代码实现:一旦我们设计好了算法和数据结构,我们可以使用C语言来实现它们。根据数据结构的不同,可能会使用到C语言的指针、结构体、递归等特性来完成实现。 4. 测试和验证:完成代码实现后,我们需要编写一些测试用例来验证代码的正确性和性能。通过不同的测试用例,我们可以检查代码是否满足预期的需求,并且确认代码的运行效率。 5. 优化和修改:在测试过程中,我们可能会发现一些代码的问题或者可以进一步优化的地方。在保证代码正确性的前提下,我们可以对代码进行优化,提高其运行效率和性能。 通过上述步骤,我们可以实现王道数据结构C。通过编写和理解代码,我们可以更深入地学习和理解数据结构的原理和应用,提高自己的编程能力和解决问题的能力。同时,也可以帮助我们更好地理解和掌握C语言的使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值