JHHK

欢迎来到我的个人网站
行者常至 为者常成

8、析构函数、命名空间、类的声明和实现

目录

析构函数的作用

class Car8{
public:
    int price;
    
    Car8(){
        cout<<"Car::Car()"<<endl;
        price = 2000;
    }
    
    ~Car8(){
         cout<<"Car::~Car()"<<endl;
    }
};


class Person8{
private:
    int age;
    Car8 * car;
public:
    // 对象创建完毕的时候调用 初始化操作
    Person8(){
        cout<<"Person::Person()"<<endl;
        age = 18;
        car = new Car8();
    }
    
    // 对象销毁(内存被回收)的时候调用 回收指针变量指向的堆空间
    ~Person8(){
        cout<<"Person::~Person()"<<endl;
        
        //对象内部申请的堆空间,由对象内部回收
        delete car;
    }
};

class Person8_2{
public:
    int age;
    Car8 car;
    
    Person8_2(){
        cout<<"Person8_2()"<<endl;
    }
    
    ~Person8_2(){
        cout<<"~Person8_2()"<<endl;
        
        //此处不要回收car的内存空间,是因为 car在此处不是指针变量,内存空间在Person8_2对象内,
        //当Person8_2对象回收的时候,car会被一并回收
    }
};



void destructorUsing(){
    {
        //person对象在栈空间
        //car指针变量在栈空间,属于person的一部分
        //car存储的地址指向堆空间
        Person8 person;//栈空间创建一个Person对象
    }
    
    //离开person的作用域,person的内存被回收,调用析构函数
    //perosn的成员变量
    //age 被回收
    //指针变量 car被回收 参car指向的那块堆空间未被回收,需要在person的析构函数内处理
    
    cout<<"=================="<<endl;
    
    {
        //person对象在栈空间
        //car变量在栈空间属于person2的一部分
        Person8_2 person2;
    }
    
     
    cout<<"=================="<<endl;
    
    {
        //该情况的内存分布图 见图片 memoryOfPerson3.png
        Person8 * person3 = new Person8;
        delete person3;
    }
    
    cout<<"=================="<<endl;
    
    {
        Person8_2 * person4 = new Person8_2;
        delete person4;
    }
    
    
    /**
     person1、person2、person3、person4的内存分布一定要搞清楚
     */
}

命名空间

命名空间可以用来避免命名冲突

命名空间不影响内存布局

命名空间可以嵌套

有个默认的全局命名空间,我们创建的命名空间默认都嵌套在它里面

相同的命名空间会合并

OC里边同样有命名空间的概念,那就是在类的前面加前缀。LCPerson;MJPerosn;

int g_age;

void g_run(){
    cout<<"::g_run"<<endl;
}




namespace LC {

//注意这是个全局变量(放在命名空间内不影响它仍是一个全局变量)
int g_age;

//注意这是一个全局函数
void g_run(){
    cout<<"LC::g_run"<<endl;
}


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

}




namespace MJ {

//注意这是个全局变量(放在命名空间内不影响它仍是一个全局变量)
int g_age;

//注意这是一个全局函数
void g_run(){
    cout<<"MJ::g_run"<<endl;
}


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

}

void namespaceUsing(){
    LC::Person person1;
    person1.run();
    
    MJ::Person person2;
    person2.run();
}


void namespaceUsing1(){
    using namespace LC;
    Person person;
    person.run();
    
    MJ::Person person2;
    person2.run();
}


void namespaceUsing2(){
    using namespace LC;
    using namespace MJ;

    
    ::g_age = 10;
    ::g_run();
    
    
    LC::g_age = 11;
    LC::g_run();
    
    MJ::g_age = 12;
    MJ::g_run();
    
    LC::Person person1;
    person1.run();
    
    MJ::Person person2;
    person2.run();
    
}

void namespaceUsing3(){
    using LC::Person;
    Person person;
    person.run();
}

类的声明与实现

//类的声明:类的声明可以放在 .h文件内,同时可以加上命名空间
class PersonClass{
private:
    int age;
public:
    void setAge(int age);
    
    int getAge();
    
    PersonClass();
    
    ~PersonClass();
    
};

//类的实现
void PersonClass::setAge(int age){
    this->age = age;
}

int PersonClass::getAge(){
    return this->age;
}

PersonClass::PersonClass(){
    cout<<"PersonClass()"<<endl;
}

PersonClass::~PersonClass(){
    cout<<"~PersonClass()"<<endl;
}




//类的实现
namespace LCClass {

void PersonClass::setAge(int age){
    this->age = age;
}

int PersonClass::getAge(){
    return this->age;
}

PersonClass::PersonClass(){
    cout<<"LCClass::PersonClass()"<<endl;
}

PersonClass::~PersonClass(){
    cout<<"LCClass::~PersonClass()"<<endl;
}
}


void compleUsing(){
    PersonClass personcl1;
    
    LCClass::PersonClass personcl2;
}

继承

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

关系描述
Student是子类(subclass,派生类)
Person是父类(superclass,超类)

C++中没有像Java、Objective-C的基类
Java:java.lang.Object
Objective-C:NSObject

父类与子类成员变量的内存分配
父类的成员变量在前,子类的成员变量在后

struct Person{
    int age;
    void run(){
        cout<<"Person::run"<<endl;
    }
};


struct Student:Person{
    int number;
    void study(){
        cout<<"Student::study"<<endl;
    }
};


struct Worker:Person{
    int company;
    void work(){
        cout<<"Worker::work"<<endl;
    }
};


void inheritUsing(){
    Student * stu = new Student();
    stu->age = 18;
    cout<<"stu->age is "<<stu->age<<endl;
    
    Worker * wor = new Worker();
    wor->age = 28;
    cout<<"wor->age is "<<wor->age<<endl;
}

成员访问权限

成员访问权限、继承方式有3种
public:公共的,任何地方都可以访问(struct默认)
protected:子类内部、当前类内部可以访问
prvate:私有的,只有当前类内部可以访问(class默认)

子类内部访问父类成员的权限,是以下2项中权限最小的那个
成员本身的访问权限
上一级父类的继承方式

开发中用的最多的继承方式是public,这样能保留父类原来的成员访问权限

访问权限不影响对象的内存布局

class PersonTwo{
    int age;
protected:
    int address;
public:
    int height;
    void run(){}
};


class StudentTwo: public PersonTwo{
public:
    int number;
    void study(){
//        this->age = 17;   //私有成员变量只有类内部可以访问
        this->address = 12; //保护成员变量,父类、子类都可以访问
        this->height = 181; //公开成员变量,父类、子类、外部都可以访问
    }
};


class WorkerTwo: public PersonTwo{
public:
    int company;
    void work(){}
};


void memberPermission(){
    StudentTwo * stuTwo = new StudentTwo();
    
    //stuTwo->age = 18;     //私有成员变量外部不可访问
    //stuTwo->address = 10; //保护属性外部不可访问
    stuTwo->height = 180;   //公开成员变量外部可以访问
    cout<<"stuTwo->height is "<<stuTwo->height<<endl;
    
    delete stuTwo;
}


行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.