C++面向对象程序设计I -- 侯捷版

1. 防卫式声明

为了防止在别的文件里引用该头文件,不讲究include顺序。
第一次引用的时候,会先判断是否被定义过,如果之前没有被定义过,就定义该头文件。避免重复引用Include。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

访问权限 access level

在定义一个class的时候,数据使用private权限
在这里插入图片描述

构造函数

在这里插入图片描述
空构造函数与有默认值的构造函数不能同时出现,因为会迷惑编译器,让编译器不知道选择哪一个构造函数构造。
在这里插入图片描述

参数传递

尽量全部传引用,因为快,安全。速度上相当于传指针。
在这里插入图片描述
如果不想被修改,就加const
在这里插入图片描述

返回值传递

尽量返回引用;
当返回的值对象的空间原本就已经被创建,存在了。就可以返回其引用。但是如果返回的值的空间是不存在的,那么就不能传递引用。因为引用必须是引用某个对象,对象不存在,那么引用就也不存在。
在这里插入图片描述
在这里插入图片描述

操作符重载

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

总结

  1. 数据都放在private下定义,用函数返回值提取数据;
  2. 参数传递和返回值传递尽量使用引用;
  3. 能使用const就要使用;
  4. 构造函数的Initial_list要尽量使用;

大致框架

#ifndef __COMPLEX__
#define __COMPLEX__

#include <cmath>
#include<iostream>

class ostream;
class complex;
complex& __doapl(complex*,const complex&);

complex::function{...};

#endif

complex.h

#ifndef __COMPLEX__
#define __COMPLEX__

#include <cmath>
#include<iostream>

template<typename T>

class complex{
public:
    complex (T r = 0,T i = 0): re(r),im(i){
    
    }
    complex operator += (const complex& );
    double real() const { return re; }
    double imag() const { return im; }
    
private:
    T re,im;
    friend complex& __doapl(complex*,const complex&);
    
};
inline complex&
__doapl(complex* ths,const complex& r){
    ths->re += r.re;
    ths->im += r.im;
    return *ths;
}

inline complex& 
    complex::operator +=  (const complex& r){  //右边加到左边,右边是不变的,加const
    return __doapl(this, r);
}

//全局函数
inline complex
operator + (const complex& x, const complex& y){
    return complex( real(x) + real(y),
                    imag(x) + imag(y) );  //临时对象
}

inline complex
operator + (const complex& x, double y){
    return complex( real(x) + y, imag(x) );  //临时对象
}

inline complex
operator + (const double x, complex& y){
    return complex( x + real(y), imag(y) );  //临时对象
}

ostream&
operator << (ostream& os,const complex& x){
    return os << "(" << real(x) << "," << imag(x) << ")";
}inline double image(const complex& x){
    return x.imag();   //返回复数的虚部
}

inline complex&
__doapl(complex& ths,const complex& r){
    ths->re += r.re;
    ths->im += r.im;
    return *th
}

inline complex& 
    complex::operator +=  (const complex& r){  //右边加到左边,右边是不变的,加const
    return __doapl(this, r);
}

#endif

complex.cpp

#include "complex.h"
#include "iostream.h"

ostream&
operator << (ostream& os,const complex& x){
    return os << "(" << x.real() << "," << x.imag() << ")";
}

main.cpp

#include "complex.h"

int main(){
    complex<double> c1(2,1);
    complex<double> c2;
    ...
}

2. big three 三大函数:拷贝构造、拷贝赋值、析构

例如:

String s1();
String s2("hello");
String s3(s2);

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
浅拷贝,赋值拷贝,a,b指针指向同一个内存hello,但是当a或者b发生改变的时候,另一个都会改变;拷贝指针是浅拷贝,分配空间是深拷贝。

拷贝赋值函数

在这里插入图片描述
先检查是否是自我赋值: a = a;

if(this == &str){
    return *this;    //自我赋值,一方面可以提高效率,同时在在自我赋值下可以保证正确性。
}

在这里插入图片描述
在这里插入图片描述
先确定是否有自我赋值的情况,要不然直接delete就会导致内存泄漏。

总结

string.h

#ifndef __MYSTRING__
#define __MYSTRING__

class String{
publicString(const char* cstr = 0);
    String(const String& str);  			//拷贝构造
    String& operator=(const String& str);  //拷贝赋值
    ~String();
    char* get_c_str() const { return m_data; }

privatechar* m_data;
};

#endif

string_test.cpp

#include "String.h"

inline String::String(const char* cstr = 0){
    if(cstr){
        m_data = new char[strlen(cstr) + 1];
        strcpy(m_data, cstr);
    }
    else{  //未指定初值
        m_data = new char[1];
        *m_data = '\0';
    }
}

//拷贝构造
inline String::String(const String& str){
    m_data = new char[strlen(str.m_data) + 1];
    strcpy(m_data, str.m_data);
}

inline String& String::operator=(const String& str){
   //检查是否是自我赋值
    if(this == &str){  //取地址
        return *this;
    }
    
    delete[] m_data;
    m_data = new char[strlen(str.m_data) + 1];
    strcpy(m_data, str.m_data);
    
    return *this;
}

String::~String(){
    delete[] m_data;
}

3. 生命周期

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在每次开辟新空间的时候,结束时候要释放空间回收,否则就会出现空间还在,但是指向该空间的指针已经被回收,出现野指针。内存泄漏
指向那块内存的指针已经死掉了,但是内存还在,还没释放掉。就是内存泄漏。

4. new

在这里插入图片描述
先通过operator new()分配内存,(内部调用malloc),再调用构造函数。
回收内存的时候,是先调用析构函数,再释放内存(内部调用free)。
在这里插入图片描述delete先杀掉字符串本身,也就是指针m_data,第二步回收动态分配的内存;free
在这里插入图片描述

5. 类与类之间的关系

在这里插入图片描述

复合

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

委托

定义一个另外的类,某一个功能给另外的类来完成
在这里插入图片描述

继承

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
父类的析构函数必须是virtual,方便子类空间回收,否则会出现内存泄漏。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

委托+继承

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值