C++-02、命名空间、构造函数、析构函数

2022-07-27  本文已影响0人  喂_balabala
命名空间

#include <iostream>

// 声明std,我们的main函数就可以直接使用里面的成员,不需要使用 std::
using namespace std; // C++自己的命名空间 (C# .net 命名空间)

// 自定义命名空间
namespace derry1 {
    int age = 33;
    char * name = "Derry猛男1";

    void show() {
        cout << "name:" << name << ", age:" << age << endl;
    }

    void action() {
        cout << "derry1 action" << endl;
    }
}

// TODO ------ 命名空间里面重复的函数
// 自定义命名空间
namespace derry2 {
    void action() {
        cout << "derry2 action" << endl;
    }
}

// TODO ------ 小概率会遇到的情况,命名空间的嵌套
// 自定义命名空间
namespace derry3 {
    namespace derry3Inner {
        namespace derry3Inner1 {
            namespace derry3Inner2 {
                namespace derry3Inner3 {
                    void out() {
                        cout << "爱恨情仇人消瘦,悲欢起落人寂寞" << endl;
                    }
                }
            }
        }
    }
}

// 声明各个写的 命名空间
// using namespace derry1;

int main() {
    cout << "命名空间" << endl;

    // 声明各个写的 命名空间
    using namespace derry1;

    int ageValue = derry1::age; // 方式1 使用 刚刚声明的命名空间
    derry1::show(); // 使用 刚刚声明的命名空间

    ageValue = age; // 方式2 直接去引出来 ::
    show(); // 直接去引出来 ::


    // TODO ------ 命名空间里面重复的函数
    using namespace derry2;
//     action(); 很尴尬
    derry1::action();
    derry2::action();

    // TODO ------ 小概率会遇到的情况,命名空间的嵌套

    // 第一种方式 先声明命名空间  再使用
    using namespace derry3::derry3Inner::derry3Inner1::derry3Inner2::derry3Inner3;
    // 再使用
    out();

    // 第二种方式 直接使用
    derry3::derry3Inner::derry3Inner1::derry3Inner2::derry3Inner3::out();

    return 0;
}


构造函数、析构函数
#include <iostream>
#include <string.h>
using namespace std;

class Student {

// 构造函数
public:
    // 空参数构造函数
    Student() {
        cout << "空参数构造函数" << endl;
    }

    // 一个参数的构造函数
    // :Student(name, 87) 等价 1.调用两个参数的构造函数, 2.再调用当前函数
    Student(char *name) :Student(name, 87) {
        cout << "一个参数的构造函数" << endl;
        this->name = name;
    }
    // 系统源码中是写的
    // :name(name) 等价 this->name = name;
    /*Student(char * name) :name(name) {
        cout << "一个参数的构造函数" << endl;
    }*/

    // 两个参数的构造函数
    Student(char *name, int age) {
        // this->name = name;

        // 堆区
        this->name = (char *) (malloc(sizeof(char *) * 10));
        strcpy(this->name, name);

        this->age = age;
        cout << "两个参数的构造函数" << endl;
    }

    // 析构函数 Student对象的,临终遗言,Student对象被回收了,你做一些释放工作
    // delete stu 的时候,我们的析构函数一定执行
    // free不会执行析构函数,也意味着,你没法在析构函数里面,做释放工作, malloc也不会调用构造函数
    ~Student() {
        cout << "析构函数" << endl;

        // 必须释放 堆区开辟的成员
        if (this->name) {
            free(this->name);
            this->name = NULL; // 执行NULL的地址,避免出现悬空指针
        }
    }

// 私有属性
private:
    char *name;
    int age;

// 公开的 set get 函数
public:
    int getAge() {
        return this->age;
    }

    char *getName() {
        return this->name;
    }

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

    void setName(char *name) {
        this->name = name;
    }
};

int main() {
    // TODO  =========== 下面是栈区 开辟空间的

    /*Student stu; // 调用 空参数构造函数
    stu.setAge(34);
    stu.setName("李元霸");
    cout << "name:" << stu.getName() << ", age:" << stu.getAge() <<  endl;*/

    // Student stu("雄霸", 30);
    /*Student stu("李连杰");
    cout << "name:" << stu.getName() << ", age:" << stu.getAge() <<  endl;*/

    // TODO =========== 下面是堆区 开辟空间的  堆区必须手动释放,否则内存占用越来

    // 系统源码中,会看到,很多使用 new 关键字

    // *stu  ->:调用一级指针的成员
    // new/delete
    // C++中,必须使用 new/delete 一套
    Student *stu = new Student("杜子腾", 26);
    cout << "name:" << stu->getName() << ", age:" << stu->getAge() <<  endl;
    delete stu;

    // free(stu); 这样写是不规范的,不按人家规则来

    // 还有人这样写 (C工程师,搞了六年,改不了自己的习惯, malloc)
    // malloc 你的构造函数都没有调用,这个不行的
    /*Student *stu2 = (Student*) malloc(sizeof(Student));
    free(stu2);*/

    // 纠结:C++有析构函数(临终遗言 释放工作)    Java KT 临终遗言 是什么?

    return 0;
}

Java/KT的所谓的析构函数
package test;

import java.io.Closeable;
import java.io.IOException;

// 隐式 extends Object
public class JavaHelp implements Closeable {
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        close();
    }

    @Override
    public void close() throws IOException {
    }
}

package test;
// 默认隐式  extends Object
public class Stu {
    // 并不是说,Java调用了finalize函数,代表这个类可能被回收了(只是回收的前兆)
    // 此类加入到queue队列中,等待虚拟机来处理(只有虚拟机处理回收了,才叫回收)
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("Java 我被回收了");
    }
}

package test
// 隐式的 : Any?
// KT做不到,但是可以借助Java来做
class Student : JavaHelp() {
    override fun close() {
        super.close()
        println("KT 我被回收了");
    }
}

package test;

public class Main {

    public static void main(String[] aaa) {
        // ====== Java 回收
        Stu stu = new Stu();
        stu = null;
        System.gc(); // (如果没有stu = null)gc机制来扫描吧,gc一过来发现,stu还有指向,扫你妹啊

        // ===== KT 回收
        Student student = new Student();
        student = null;
        System.gc();;
    }
}

new/delete 是一套 会调用构造函数 与 析构函数 【C++标准规范】
malloc/free是一套 不调用构造函数 与 析构函数 【C的范畴,虽然不推荐,但是也是可以的】
拷贝构造函数
#include <iostream>
#include <string.h>

using namespace std;

class Student {

public:
    Student() { cout << "空参数构造函数" << endl; }

    // 两个参数的构造函数
    Student(char *name, int age) : name(name), age(age) {
        cout << "两个参数构造函数" << endl;
    }

    // 析构函数
    // ~Student(char * name) { } 这样写,就不是析构函数了,如果你这样写,C/C++编译器对你很无语
    ~Student() {
        cout << "析构函数" << endl;
    }

    // 以前是默认有一个拷贝构造函数,stu2 = stu1 默认赋值 【隐式 你看不到】

    // 拷贝构造函数,它默认有,我们看不到,一旦我们写拷贝构造函数,会覆盖她
    // 对象1 = 对象2
    // 覆盖拷贝构造函数
    Student(const Student & student) { // 常量引用:只读的,不让你修改
        cout << "拷贝构造函数" << endl;

        // 我们自己赋值
        // 为什么要自己赋值,自己来控制,就可以 例如:-10
        this->name = student.name;
        this->age = student.age - 10;

        cout << "自定义拷贝构造函数 内存地址 " << &student << endl;
    }

// 私有属性
private:
    char *name;
    int age;

// 公开的 set get 函数
public:
    int getAge() {
        return this->age;
    }

    char *getName() {
        return this->name;
    }

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

    void setName(char *name) {
        this->name = name;
    }
};

struct Person {
    int age;
    char *name;
};

// TODO = 号的意义 隐式代码,引出 拷贝构造函数
/*
int main() {
    Person person1 = {100, "张三丰"};

    // = 你看起来,没有什么特殊,隐式的代码:你看不到  C/C++编译器 会把p1的成员值赋值给p2成员
    Person person2 = person1;

    cout << &person1 << endl;
    cout << &person2 << endl;

    cout << person2.name << ",  " << person2.age << endl;

    // 思考:对象 对象1=对象2  默认的 拷贝构造函数

    return 0;
}*/

// TODO  拷贝构造函数
/*
int main() {
    Student stu1("李鬼", 34);
    Student stu2 = stu1;

    cout << stu2.getName() << " , " <<  stu2.getAge() <<  endl;
    cout << "main " << &stu1 << endl; // 这里地址的打印和拷贝构造函数里地址的打印是一样的,  注意:cnetos的环境 地址打印有差异,要注意

    // TODO  拷贝构造函数的注意点:
    // Student stu1("李鬼", 34);

    // Student stu2;
    // stu2 = stu1; // 这样赋值是不会调用自定义拷贝构造函数的,但是会调用默认赋值
    // Student stu2 = stu1;  // 这样赋值是会调用自定义拷贝构造函数,我们自己赋值

    // cout << stu2.getName() << " , " <<  stu2.getAge() <<  endl;

    getchar(); // 程序等待在这一行

    return 0;
} // main函数弹,stu1栈成员会回收  stu2栈成员会回收
*/

// TODO 这种写法 拷贝构造函数  到底会不会调用
int main() {
    Student *student1 = new Student("杜子腾", 39);

    Student *student2 = student1;  // 压根就不会执行拷贝构造函数(指针指向问题,和我们刚刚那个  对象2=对象1 是两回事)

    student2->setAge(99);

    cout << student1->getName() << student1->getAge() << endl;

    // “->”调用一级指针的成员    和    “.”非指针的操作  有啥区别

    return 0;
}
Student *student1 = new Student("杜子腾", 39); Student *student2 = student1;为什么不走拷贝构造函数?
上一篇下一篇

猜你喜欢

热点阅读