C++笔记01

55 阅读1分钟

Object Based(基于对象) vs Object Oriented(面向对象)

Object Based:面向的是单一class的设计
Object Oriented:面对的是多重classes的设计,classes和classes之间的关系。

第一篇笔记主要记录Object Based。

Object Based

单个类有两个经典分类:

  1. Class without pointer member(s) 如:Complex
  2. Class with pointer member(s) 如:String

常量成员函数

常成员函数是指由const修饰符修饰的成员函数,在常成员函数中不得修改类中的任何数据成员的值。

double real () const {return re;}
class complex
{
public:
    complex (double r = 0, double i = 0)
    : re (r), im(i)
    { }
    complex& operator += (const complex&);
    double real () const {return re;}
    double imag () const {reutn im;}
private:
    double re, im;

    friend complex& __doapl (complex*, const complex&);
};

这样是为了让用户正确使用时不骂你。 用户可能如下操作:

{
    const complex c1(2,1);//我这个值是不能改变的哦
    cout << c1.real();//万一real函数没写const,就可能改data。就会产生矛盾
    cout << c2.imag();
}

如果不使用常成员函数,就会报错。

三大函数(Big Three):拷贝构造

【注】拷贝构造、拷贝赋值,在带有指针的情况下,不能用编译器自带的那一套,需要自己编写。

class String
{
public:
    String(const char* cstr = 0);
    String(const String& str);//拷贝构造
    String& operator=(const String& s);//操作符重载(拷贝赋值)
    ~String();//析构函数
    char* get_c_str() const { return m_data};//inline
private:
    char* m_data;
};
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()
{
    delete[] m_data;
}

inline String& String::operator=(const String&)
{
    if(this == &str)//检测自我赋值(self assignment)
        return *this;
    
    delete[] m_data;//杀掉自己
    m_data = new char[strlen(str.m_data) + 1];//重新创造自己
    strcpy(m_data, str.m_data);//拷贝过来
    return *this;  
}

【注】这样做不仅是为了提高效率,不做还会影响正确性。

new 和 delete

new指令实际上是先分配Memory,再调用构造函数

 Complex* pc = new Complex(1, 2); 

编译器转化为

Complex *pc;

void* mem = operator new(sizeof(Complex));//分配内存
pc = static_cast<Complex*>(mem);//转型
pc->Complex::Complex(1, 2);//构造函数

operator new是一个函数,其内部调用malloc(n)

delete指令实际上是先调用析构函数,再释放Memory

Complex* ps = new Complex(1, 2);
...
delete ps;

编译器转化为

Complex::~Complex(ps);//析构函数\
operator delete(ps);//释放内存\

delete函数内部调用free(ps)

array new 一定要搭配 array delete

因为array delete 需要先执行len次析构函数,再释放Memory,而单纯的delete则只执行一次析构函数,然后就释放Memory了。

image.png