C++ 可变参数,this,static,友元函数,友元类

177 阅读5分钟

1、可变参数

C++的可变参数,和Java的比起来感觉有点不太智能的样子。需要引入一个库来实现。 stdarg
在使用的过程中先定义一个va_list可变参数列表。

这时va_list是不可用的,需要调用方法 va_start 这个方法需要将va_list传进去,并且需要传递一个int 值,这个值初始值是任何值都没关系,但建议是和可变参数一块传进来,值建议为可变参数的长度,这样方便遍历可变参数。

使用va_arg 这个方法获取可变参数的值,两个参数 第一个参数 va_list,第二个参数,可变参数的类型。

最后,要使用va_end 来关闭va_list

//可变参数
void testArgs(int count,...) {
    cout <<"cout的值"<< count <<endl;
    va_list vp; //可变参数的动作
    //参数一  可变参数的动作
    //参数二 需要一个int,stdarg 需要一个int 来记录 可变参数的位置
    //内部需要一个存地址用的参考值,如果没有第二个参数,内部无法处理存放参数信息
    va_start(vp,count);

    //到这里后,vp就有丰富的值了;
    //获取可变参数第一个值
    int number = va_arg(vp,int);
    cout << number <<endl;// 1
    //获取可变参数的第二个值
    int number2 = va_arg(vp,int);
    cout << number2<<endl; //5
    //获取可变参数的第三个值
    int number3 = va_arg(vp,int);
    cout << number3<<endl;//6

    //count 的第二个作用 循环 和上面的写法 二选一
    // for (int i=0;i<count;++i) {
    //     int number3 = va_arg(vp,int);
    //     cout << number3<<endl;//6
    // }
    //关闭
    va_end(vp);
}
int main () {
    testArgs(3,1,5,6,8,1,5);
    return 0;
}

2、static 关键字

在类中可以定义static 修饰的 成员变量,但是不能在定义的地方进行,初始化。编译都不会通过。不允许这样干。

在构造方法里也不允许初始化。编译成功,运行报错。
静态函数里赋值。也不可以。

错误写法

class Person {
    public:
        char * name;
        int age;
        static int id =9;//会报错 static data member cannot have an in-class initializer
        Person() {
            id =10;//会报错
        }
        static void updateAge() {
            id =10;//会报错
        }
        void updateAge2() {
            id= 15;//会报错
        }
};

正确写法

class Person {
    public:
        char * name;
        int age;
        //先声明
        static int id;
        Person() {
            id =10;//可以修改
            cout<< id <<endl;
        }
        static void updateAge() {
            id =10;//可以修改
        }
        void updateAge2() {
            id= 15;//可以修改
        }
};
//再实现 
int Person::id = 10;
int main(int argc, char *argv[]) {
    Person person;
    person.updateAge2();
    Person ::updateAge();
    return 0;
}

int Person::id = 10;没有这句代码,在类中的 static id,是没有在静态区中开辟空间的,也就是没有引用可以找到它的。所以你初始化就会报错。int Person::id = 10这句代码执行了,静态区里才会有一个 别名为id 数据类型为 int 的数据存在的。

可以直接通过类名::静态成员(字段函数)调用。也可以通过对象.静态方法这种在C++中是支持的,但是不建议这样用。推荐规范写法 冒冒的写法。
静态的属性必须要初始化,然后再实现。(规则) 静态的函数只能去操作静态的属性和方法。和Java一样。

3、辨析常量指针,指针常量,常量指针常量

image.png

const int * numberP1;
常量指针 不允许修改常量指针存放地址所对应的值,允许重新指向常量指针存放的地址。

int * const numberP2;

指针常量 允许修改指针常量存放地址所对应的值。不允许重新指向指针常量存放的地址

const int * cosnt numberP3;

常量指针常量 不允许修改常量指针常量存放地址所对应的值。不允许重新指向常量指针常量存放的地址

image.png

4、this 关键字

为什么需要this关键字?

伪代码

main  {
    Student  stu1;
    stu1.setAge(8);
    Student stu2;
    stu2.setAge(10);
}

问题一: stu2.setAge是怎么知道给stu2这个对象的age 赋值的呢?

image.png

Student 在执行构造函数时,会在栈区开辟一块空间。然后会存放一个this(指针),这个指针指向代码区存放函数体的地方。这样就能精确的将值赋给stu1 和stu2了。

问题二 const 修饰函数屁股,有什么效果?

class Person {
    public:
        char * name;
        int age;

        void updateAge2(){
            //此时this Student *const this; 指针常量, 可以修改其地址对应的值。
            //不能修改this的值(地址)
          this->age =10;
            //this =0x2233;//不能修改
        }
        //const 修饰函数屁股
        void updateAge3() const{//成员变量只读
            //此时this cosnt Student *const this 常量指针常量
            //在这个方法里不能修改成员变量的值,
            //this->age =10;//不能修改
           // this =0x446;//不能修改
        }
};

5、友元函数、友元类

在C++的类中,有私有成员,我们是不能访问的。自己的宝贝,只能自己玩,,别人不能玩的。自己的宝贝让别人玩,你放心么。但是你想玩我的宝贝怎么办,只能成为我的好基友才可以哦。不是普普通通的好基友。是超越了亲情和爱情的好基友才可以玩我的宝贝。所以C++ 有了友元函数。

class Person {
private:
    int age= 0;
    //声明友元函数,在类中只声命不实现
    friend void updateAge(Person * personP);
};
void updateAge(Person * personP) {
    //可以拿到所有私有成员
    personP->age;//这样就可以玩Person的宝贝了
}
int main(int argc, char *argv[]) {
    Person person;
    updateAge(&person);
    return 0;
}
private:
    int age= 0;
    //声明友元函数,在类中只声命不实现
    friend void updateAge(Person * personP);
    friend class Class;//声明友元类
};
//在Java中每个类都会有一个Class ,这个Class 可以操作对象的私有成员
class Class {
    Person person;
    void changeAge(int age) {
        person.age =age;//可以修改
    }
};