C++-04、可变参数、static关键字、const修饰函数的this、实战类写法、友元

可变参数
#include <iostream>
#include <stdarg.h> // 可变参数的支持
using namespace std;

// Java的可变参数: int ...
// C++的可变参数写法:...
// count的第一个用处:内部需要一个 存储地址用的参考值,如果没有这个参数,内部他无法处理存放参数信息
void sum(int count, ...) {
    va_list vp; // 可变参数的动作

    // 参数一:可变参数开始的动作vp
    // 参数二:内部需要一个 存储地址用的参考值,如果没有第二个参数,内部他无法处理存放参数信息
    va_start(vp, count);

    // 到这里后:vp就已经有丰富的信息

    // 取出可变参数的一个值
    int number  = va_arg(vp, int);
    cout << number << endl;

    // 取出可变参数的一个值
    number  = va_arg(vp, int);
    cout << number << endl;

    // 取出可变参数的一个值
    number  = va_arg(vp, int);
    cout << number << endl;

    // 越界 系统值 乱码
    // 取出可变参数的一个值 【取不到后,会取系统值 乱码】
    number  = va_arg(vp, int);
    cout << number << endl;

    // 关闭阶段
    va_end(vp);
}

// 1.可变参数
int main() {
    std::cout << "同学们大家好,我是Derry" << std::endl;

    sum(546, 6,7,8);

    return 0;
}
可变参数count变量的第二个用处
#include <iostream>
#include <stdarg.h> // 可变参数的支持
using namespace std;

// Java的可变参数: int ...
// C++的可变参数写法:...

// count变量的第二个用处,用于循环遍历长度
void sum(int count, ...) {
    va_list vp; // 可变参数的动作

    // 参数一:可变参数开始的动作vp
    // 参数二:内部需要一个 存储地址用的参考值,如果没有第二个参数,内部他无法处理存放参数信息
    va_start(vp, count);

    // 到这里后:vp就已经有丰富的信息

    for (int i = 0; i < count; ++i) {
        int r = va_arg(vp, int);
        cout << r << endl;
    }

    // 关闭阶段(规范:例如:file文件一样 要关闭)
    va_end(vp);
}

// 1.可变参数
int main() {

    sum(3, 6,7,8); // 真实开发过程的写法

    return 0;
}
static关键字错误示范
// 2.C++static关键字。 错误的写法

#include <iostream>

using namespace std;

class Dog {
public:
    char * info;
    int age;

    // 已经编译不成功,不允许这样初始化
    // static int id = 9;
    static int id;

    Dog() {
        // 运行报错
        // id = 9;
    }

    static void update() {
        // 运行报错
        // id = 9;
    }

    void update2() {
        // 运行报错
        // id = 9;
    }
};

int main() {
    Dog dog;
    Dog::update(); // 类名::可以调用静态函数
    return 0;
}
static关键字正确写法
// 2.C++static关键字。 正确的写法

/**
 * 静态的总结:
 * 1.可以直接通过类名::静态成员(字段/函数)
 * 2.静态的属性必须要初始化,然后再实现(规则)
 * 3.静态的函数只能取操作静态的属性和方法(Java)
 */

#include <iostream>

using namespace std;

class Dog {
public:
    char * info;
    int age;

    // 先声明
    static int id;

    static void update() {
        id += 100;

        // 报错:静态函数不能调用非静态函数(Java)
        // update2();
    }

    void update2() {
        id = 13;
    }
};

// 再实现
int Dog::id = 9;

int main() {
    Dog dog;
    dog.update2(); // 普通函数
    Dog::update(); // 静态函数
    dog.update(); // 对象名.静态函数(一般都是使用::调用静态成员,这种方式可以 知道就行)

    cout << Dog::id << endl;
    return 0;
}

this
#include <iostream> // iostream.h 早期C++的方式

using namespace std;

class Student {
private:
    char *name;
    int age;

public:
    static int id; // 先声明

public:
    void setName(char *name) {
        this->name = name;
    }
    void setAge(int age) {
        this->age = age;
    }
    char *getName() {
        return this->name;
    }
    int getAge() {
        return this->age;
    }

public:
    // 默认的构造函数 栈区开辟空间 暴露 地址 == this指针 (和Java一致的思路)
};

// 再实现
int Student::id = 9527;

int main() {

    //四大区:栈区、堆区、全局区(静态区、常量区、字符串区)、代码区

    // ======= 常规使用下而已
    Student student;
    student.setAge(99);
    student.setName("Derry");
    cout << student.getName() << " , " << student.getAge()<< endl;

    // ==========  this 纠结   setAge在代码区,有多个副本,对应不用指针
    Student student1;
    student1.setAge(88); // 设置值的时候,它怎么知道是给student1的age设置值的?
    student1.id = 880;

    Student student2;
    student2.setAge(99); // 设置值的时候,它怎么知道是给student2的age设置值的?
    student2.id = 990;

    Student::id = 666;

    // 它怎么知道是获取student1的age
    cout << " student1.getAge:" << student1.getAge() << endl;

    // 它怎么知道是获取student2的age
    cout << " student2.getAge:" << student2.getAge() << endl;

    cout << "student1.id:" << student1.id << endl;
    cout << "student2.id:" << student2.id << endl;
    cout << "Student:::" << Student::id << endl;


    return 0;
} // main函数弹栈会 隐式代码:(栈区:delete student ..., 堆区需要自己手动delete)


const修饰函数的this意义何在
#include <iostream>

using namespace std;

// 如果是面试C++岗位,会被回到,不然问不到

class Worker {
public:
    char * name;
    int age = NULL; // C++中不像Java,Java有默认值, 如果你不给默认值,那么就是系统值 -64664

    // int * const  指针常量 指针常量【地址对应的值能改,地址不可以修改】
    // const int *  常量指针 常量指针【地址可以修改,地址对应的值不能改】

    // 纠结:原理:为什么可以修改age
    // 默认持有隐式的this【类型 * const this】
    // 类型 * const 指针常量:代表指针地址不能被修改,但是指针地址的值是可以修改的
    void change1() {
        // 代表指针地址不能被修改
        // this = 0x6546;  // 编译不通过,地址不能被修改,因为是指针常量
        // 地址不可以修改
        // this = 0x43563;

        // 隐士的this
        // 但是指针地址的值是可以修改的
        // 地址对应的值能改
        this->age = 100;
        this->name = "JJJ";
    }

    // 默认现在:this 等价于 const Student * const  常量指针常量(地址不能改,地址对应的值不能改)
    void changeAction() const {
        // 地址不能改
        // this = 0x43563;

        // 地址对应的值不能改
        // this->age = 100;
    }

    // 原理:修改隐式代码  const 类型 * const 常量指针常量
    void showInfo() const {
        // this->name = "";
        // this->age = 88;

        // 只读的
        cout << "age:" << age << endl;
    }
};

int main() {
    return 0;
}

友元函数
// 老外:你是它的好朋友,那就可以拿私有成员给好朋友

#include <iostream>

using namespace std;

class Person {
private: // 私有的age,外界不能访问
    int age = 0;

public:
    Person(int age) {
        this->age = age;
    }

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

    // 定义友元函数 (声明,没有实现)
    friend void updateAge(Person * person, int age);
};

// 友元函数的实现,可以访问所以私有成员
void updateAge(Person* person, int age) {
    // 默认情况下:不能修改 私有的age
    // 谁有这个权限:友元(拿到所有私有成员)
    person->age = age;
}

int main() {
    Person person = Person(9);
    updateAge(&person, 88);

    cout << person.getAge() << endl;
    return 0;
}

实际写法
  • Pig.h
#include <iostream>

using namespace std;

#ifndef PIG_H // 你有没有这个宏(Java 宏==常量)
#define PIG_H // 定义这个宏

class Pig {
private:
    int age;
    char * name;

public:
    // 静态成员声明
    static int id;

    // 构造函数的声明系列
    Pig();
    Pig(char *);
    Pig(char *,int);

    // 析构函数
    ~Pig();

    // 拷贝构造函数
    Pig(const Pig & pig);

    // 普通函数 set get
    int getAge();
    char * getName();
    void setAge(int);
    void setName(char *);

    void showPigInfo() const; // 常量指针常量 只读

    // 静态函数的声明
    static void changeTag(int age);

    // 不要这样干
    // void changeTag(int age);

    // 友元函数的声明
    friend void changeAge(Pig * pig, int age);
};

#endif // 关闭/结尾

  • Pig.cpp
#include "Pig.h"

// TODO  ======================  下面是 普普通通 常规操作 对象::

// 实现构造函数
Pig::Pig() {
    cout << "默认构造函数" << endl;
}

Pig::Pig(char * name) {
    cout << "1个参数构造函数" << endl;
}

Pig::Pig(char * name, int age) {
    cout << "2个参数构造函数" << endl;
}

// 实现析构函数
Pig::~Pig() {
    cout << "析构函数" << endl;
}

// 实现 拷贝构造函数
Pig::Pig(const Pig &pig) {
    cout << "拷贝构造函数" << endl;
}

int Pig::getAge() {
    return this->age;
}
char * Pig::getName() {
    return this->name;
}
void Pig::setAge(int age) {
    this->age = age;
}
void Pig::setName(char * name) {
    this->name = name;
}

void Pig::showPigInfo() const {

} // 常量指针常量 只读



// TODO ===============================  静态 和 友元 注意点 自己理解

// 实现 静态属性【不需要增加 static关键字】
int Pig::id = 878;

// 实现静态函数,【不需要增加 static关键字】
void Pig::changeTag(int age) {

}

// 友元的实现
// 友元特殊:不需要关键字,也不需要 对象:: ,只需要保证 函数名(参数)
void changeAge(Pig * pig, int age) {

}
友元类
// 友元类 的 小故事 (ImageView 私有成员  可以通过Class来访问,但是Class操作的native C++代码)
// 下载 JDK native代码 研究 【自己去研究】

// ImageView 私有成员  你能访问它的私有成员吗 Class
#include <iostream>

using namespace std;

class ImageView {
private:
    int viewSize;
    friend class Class; // 友元类
};

// Java每个类,都会有一个Class,此Class可以操作 ImageView私有成员(感觉很神奇)
class Class {
public:
    ImageView imageView;

    void changeViewSize(int size) {
        imageView.viewSize = size;
    }

    int getViewSize() {
        return imageView.viewSize;
    }
};

int main() {
    Class mImageViewClass;

    mImageViewClass.changeViewSize(600);

    cout << mImageViewClass.getViewSize() << endl;

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值