cplus class - yaokun123/php-wiki GitHub Wiki

一、类和对象

1.1、类

  1. c++中可以使用struct、class来定义一个类
struct和class的区别:
struct的默认权限是public
class的默认权限是private

// 类的定义
struct Person{
    // 成员变量
    int m_age;
    
    // 成员函数
    void run(){
        cout << m_age << " run() " << endl;
    }
};

// 类的定义
class Person{
public:
    // 成员变量
    int m_age;

    // 成员函数
    void run(){
        cout << m_age << " run() " << endl;
    }
};

Person person;
// 访问Person对象的成员变量
person.m_age = 10;

// 用Person对象调用成员函数
person.run();

// 通过指针间接访问person对象
Person *p = &person;
p->m_age = 30;
p->run();


// 上面代码中person对象、p指针的内存都是在函数的栈空间,自动分配和回收的。


// 变量名命名参考
全局变量:g_
成员变量:m_
静态变量:s_
常量:c_

1.2、this

对象中只保存普通成员变量,成员方法保存在代码区(只有一份)对象调用成员方法时会自动将对象地址(this)传递给函数。

二、封装

  1. 成员变量私有化,提供公共的getter和setter给外界去访问成员变量。
class Person{
private:
    int m_age;
public:
    void setAge(int age){
        m_age = age;
        //this->m_age = age;
    }
    int getAge(){
        return m_age;
        //return this->m_age;
    }
};

// 调用
Person person;
person.setAge(20);
cout << person.getAge() << endl;

三、内存空间的布局

  1. 每个应用都有自己独立的内存空间,其内存空间一般都哟哟以下几大区域。
  • 代码段
  • 数据段
  • 栈空间
  • 堆空间
  1. 堆空间 申请和释放
1、malloc/free
2、new/delete

int *p = new int;
*p = 10;
delete p;
3、new[]/delete[]

四、构造方法

构造函数,在对象创建的时候自动调用,一般用于完成对象的初始化工作。

函数名与类名相同,无返回值(void都不能写),可以有参数,可以重载,可以有多个构造函数。

一旦自定义了构造函数,必须用其中一个自定义的构造函数来初始化对象。

通过malloc分配的对象不会调用构造函数

在某些特定的情况下(待定),编译器才会为类生成空的无参的构造函数。

struct Person{
    int m_age;   // 不会生成默认的无参构造函数
};

struct Person{
    int m_age = 0;    // 生成默认的无参构造函数
};

五、默认情况下成员变量的初始化

全局区:初始化为0

栈区:没有初始化成员变量

堆区:加小括号的会初始化为0,不加

六、析构函数

析构函数在对象销毁的时候自动调用,一般用于完成对象的清理工作。

函数名以~开头,与类名同名,无返回值(void都不能写),无参,不可以重载,有且只有一个。

通过malloc分配的对象free时候不会调用析构函数

析构函数要声明为public才能够被外界正常使用

八、声明和实现分离

class Person{
private:
    int m_age;
public:
    void setAge(int age){
        m_age = age;
    }
    int getAge(){
        return m_age;
    }
    Person(){
        m_age = 0;
    }
    ~Person(){
        
    }
};

-----------------------------------------------------------------

// 声明
class Person{
private:
    int m_age;
public:
    void setAge(int age);
    int getAge();
    Person();
    ~Person();
};

// 实现
void Person::setAge(int age) {
    m_age = age;
}
int Person::getAge() {
    return m_age;
}
Person::Person() {
    m_age = 0;
}
Person::~Person() {

}

九、命名空间

默认的全局命名空间,没有名字,直接使用::访问

如果重复定义命名空间,会自动合并

// 命名空间的声明
namespace ns1{
    class Person{
    public:
        int m_age;
    };
}
namespace ns2{
    class Person{
    public:
        int m_weight;
    };
}

// 命名空间的使用
ns1::Person person1;
ns2::Person person2;

using namespace ns1;    // 说明之后的代码使用ns1的命名空间内容
Person person3;

十、继承

继承可以让子类拥有父类的所有成员(变量/函数)

子类的构造函数默认会调用父类的无参构造函数

如果子类的构造函数显式地调用了父类的有参构造函数,就不会再去默认调用父类的无参构造函数。

如果父类缺少无参构造函数,子类的构造函数必须显示调用父类的有参构造函数。

class Person{
public:
    int m_age;
    void run(){
        cout << "Person" << endl;
    }
};

class Student : Person{ // 继承
public:
    int m_class;
};

十一、成员访问权限

public:公共的在任何地方都可以访问

protected:子类内部、当前类内部可以访问

private:私有的,只有当前类内部可以访问

子类内部访问父类成员的权限,是以下2项中权限最小的那个

1、成员本身的访问权限
2、上一级父类的继承方式

十二、初始化列表

是一种便捷的初始化成员变量的方式

class Person{
public:
    int m_age;
    int m_height;
    /*Person(int age, int height){
        m_age = age;
        m_height = height;
    };*/
    Person(int age, int height) : m_age(age),m_height(height){ // 初始化列表
        
    }
};

构造函数的相会调用

class Person{
public:
    int m_age;
    int m_height;
    // 构造函数调用构造函数不能这样调用
    /*Person(){
        Person(0,0);  // 实际上是在创建一个新的Person对象
    }*/
    // 只能放到初始化列表中
    Person() : Person(0,0){
        
    }
    Person(int age, int height){
        m_age = age;
        m_height = height;
    };
};