C++ this原理与可变参数及友元函数友元类分步详解用法

 更新时间:2022年11月23日 16:49:56   作者:lpf_wei  
可变参数模板(variadic templates)是C++11新增的强大的特性之一,它对模板参数进行了高度泛化,能表示0到任意个数、任意类型的参数,这篇文章主要介绍了C++ this原理与可变参数及友元函数友元类

1.c++可变参数的应用

#include <iostream>
#include <stdarg.h>  //可变参数的支持
using namespace std;
void add(int count,...){
    va_list vp; 
    va_start(vp, count);
    // 取出可变参数的一个值
    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;
    // 越界之后取出来的是0
    number  = va_arg(vp, int);
    cout << number << endl;
    // 关闭阶段
    va_end(vp);
}
int main() {
    add(546, 6,7,8);
    return 0;
}

日志输出:
/home/ms/workspace/study/ndk/CPlusStudy/cmake-build-debug/CPlusStudy
可变参数输出
6
7
8
0

  • #include <stdarg.h> 如果使用可变参数,需要导入这个
  • Java的可变参数: int …
  • C++的可变参数写法:…
  • va_list vp : 可变参数的动作
  • va_start(vp, count):参数一:可变参数开始的动作vp,参数二:内部需要一个 存储地址用的参考值,如果没有第二个参数,内部他无法处理存放参数信息
  • 越界之后取出来的是0

项目中的应用:

int add(int count,...){
    va_list va;
    va_start(va,count);
    for (int i = 0; i < count; ++i) {
        int number=va_arg(va,int);
        cout << number << endl;
    }
    va_end(va);
}
int main() {
    std::cout << "可变参数输出" << std::endl;
    add(3, 6,7,8);
    return 0;
}

日志输出:
可变参数输出
6
7
8

第一个参数count可以作为可变参数的数量。

2.static 静态变量与静态方法

class Douluo {
public:
//    static char * name="唐三";  静态变量不能直接初始化  编译不通过
    static char * name;
    Douluo() {
//         name="唐三";  //静态变量不能在构造方法初始化
    }
    static void update() {
//        name="唐三"; //静态变量不能在静态方法初始化
        cout<<"name="<<name<<endl;
    }
    void update2() {
        // 运行报错
//         name="唐三";  //静态变量不能在非静态方法初始化
    }
};
/*静态变量正确初始化姿势*/
char* Douluo::name="唐三";
int main() {
//    std::cout << "可变参数输出" << std::endl;
//    add(3, 6,7,8);
    std::cout << "static的应用" << std::endl;
    Douluo douluo;
//    Douluo::name="唐三";  //静态变量不能在main方法初始化 会报错
    douluo.update2();
    Douluo::update(); // 类名::可以调用静态函数  调用静态方法的正确姿势
    return 0;
}

通过实际操作可知:

  • 静态变量不能在声明的时候初始化,直接编译不通过
  • 静态变量不能在构造方法初始化,运行报错
  • 静态变量不能在静态方法初始化,运行报错
  • 静态变量不能在非静态方法初始化,运行报错
  • 静态变量不能在main方法初始化运,行报错
  • 静态变量只能在类外部,main方法外部初始化:char* Douluo::name=“唐三”;
  • 静态方法使用**类名:😗*来调用

3.常量指针与指针常量

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

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

this : 本质上就是指针常量

    // 默认现在:this 等价于 const Student * const  常量指针常量(地址不能改,地址对应的值不能改)
    void changeAction() const {
        // 地址不能改
//         this = 0x43563;
        // 地址对应的值不能改
//         this->age = 80;
    }
```### Android NDK篇-C++语言之 this 原理和可变参数与友元函数友元类
#### 1.c++可变参数的应用
```c++
#include <iostream>
#include <stdarg.h>  //可变参数的支持
using namespace std;
void add(int count,...){
    va_list vp; 
    va_start(vp, count);
    // 取出可变参数的一个值
    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;
    // 越界之后取出来的是0
    number  = va_arg(vp, int);
    cout << number << endl;
    // 关闭阶段
    va_end(vp);
}
int main() {
    add(546, 6,7,8);
    return 0;
}

日志输出:
/home/ms/workspace/study/ndk/CPlusStudy/cmake-build-debug/CPlusStudy
可变参数输出
6
7
8
0

  • #include <stdarg.h> 如果使用可变参数,需要导入这个
  • Java的可变参数: int …
  • C++的可变参数写法:…
  • va_list vp : 可变参数的动作
  • va_start(vp, count):参数一:可变参数开始的动作vp,参数二:内部需要一个 存储地址用的参考值,如果没有第二个参数,内部他无法处理存放参数信息
  • 越界之后取出来的是0

项目中的应用:

int add(int count,...){
    va_list va;
    va_start(va,count);
    for (int i = 0; i < count; ++i) {
        int number=va_arg(va,int);
        cout << number << endl;
    }
    va_end(va);
}
int main() {
    std::cout << "可变参数输出" << std::endl;
    add(3, 6,7,8);
    return 0;
}

日志输出:
可变参数输出
6
7
8

第一个参数count可以作为可变参数的数量。

4.static 静态变量与静态方法

class Douluo {
public:
//    static char * name="唐三";  静态变量不能直接初始化  编译不通过
    static char * name;
    Douluo() {
//         name="唐三";  //静态变量不能在构造方法初始化
    }
    static void update() {
//        name="唐三"; //静态变量不能在静态方法初始化
        cout<<"name="<<name<<endl;
    }
    void update2() {
        // 运行报错
//         name="唐三";  //静态变量不能在非静态方法初始化
    }
};
/*静态变量正确初始化姿势*/
char* Douluo::name="唐三";
int main() {
//    std::cout << "可变参数输出" << std::endl;
//    add(3, 6,7,8);
    std::cout << "static的应用" << std::endl;
    Douluo douluo;
//    Douluo::name="唐三";  //静态变量不能在main方法初始化 会报错
    douluo.update2();
    Douluo::update(); // 类名::可以调用静态函数  调用静态方法的正确姿势
    return 0;
}

通过实际操作可知:

  • 静态变量不能在声明的时候初始化,直接编译不通过
  • 静态变量不能在构造方法初始化,运行报错
  • 静态变量不能在静态方法初始化,运行报错
  • 静态变量不能在非静态方法初始化,运行报错
  • 静态变量不能在main方法初始化运,行报错
  • 静态变量只能在类外部,main方法外部初始化:char* Douluo::name=“唐三”;
  • 静态方法使用**类名:😗*来调用

5.常量指针与指针常量

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

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

this : 本质上就是指针常量

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

方法名后边添加const 符号,表示的意思是常量指针常量,这个情况下值不能改,地址也不能改。

6.friend 友元函数

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(30);
    updateAge(&person, 31);
    cout << person.getAge() << endl;
}

日志输出:
/home/ms/workspace/study/ndk/CPlusStudy/cmake-build-debug/CPlusStudy
31

友元函数是为了私有成员在没有set方法的情况下,可以通过友元函数来访问私有成员变量。

7.友元类

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;
}

Java每个类,都会有一个Class,此Class可以操作 ImageView私有成员,友元类就类比Java的中的Class,如果去掉friend,就不能访问ImageView的成员了。

方法名后边添加const 符号,表示的意思是常量指针常量,这个情况下值不能改,地址也不能改。

8.friend 友元函数

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(30);
    updateAge(&person, 31);
    cout << person.getAge() << endl;
}

日志输出:
/home/ms/workspace/study/ndk/CPlusStudy/cmake-build-debug/CPlusStudy
31

友元函数是为了私有成员在没有set方法的情况下,可以通过友元函数来访问私有成员变量。

9.友元类

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;
}

Java每个类,都会有一个Class,此Class可以操作 ImageView私有成员,友元类就类比Java的中的Class,如果去掉friend,就不能访问ImageView的成员了。

到此这篇关于C++ this原理与可变参数及友元函数友元类分布详解用法的文章就介绍到这了,更多相关C++ this原理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言详细图解浮点型数据的存储实现

    C语言详细图解浮点型数据的存储实现

    使用编程语言进行编程时,需要用到各种变量来存储各种信息。变量保留的是它所存储的值的内存位置。这意味着,当您创建一个变量时,就会在内存中保留一些空间。您可能需要存储各种数据类型的信息,操作系统会根据变量的数据类型,来分配内存和决定在保留内存中存储什么
    2022-05-05
  • 基于Windows C++ 应用程序通用日志组件的使用详解

    基于Windows C++ 应用程序通用日志组件的使用详解

    众所周知,在调试、跟踪和执行应用程序的过程中,程序的日志能为这些工作提供大量有价值的运行信息。因此,程序的日志对应用程序的运行、维护至关重要
    2013-05-05
  • 深入解析设计模式中的适配器模式在C++中的运用

    深入解析设计模式中的适配器模式在C++中的运用

    这篇文章主要介绍了设计模式中的适配器模式在C++中的运用,通常适配器模式可以细分为类适配器和对象适配器两种情况,需要的朋友可以参考下
    2016-03-03
  • 浅谈 C++17 里的 Visitor 模式

    浅谈 C++17 里的 Visitor 模式

    Visitor模式经常用于将更新的设计封装在一个类中,并且由待更改的类提供一个接受接口,其关键技术在于双分派技术,本文主要介绍 C++17 里的 Visitor 模式的相关资料,需要的朋友可以参考下面文章的具体内容
    2021-09-09
  • C语言链表实现歌手评分系统

    C语言链表实现歌手评分系统

    这篇文章主要为大家详细介绍了C语言链表实现歌手评分系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-03-03
  • va_list(),va_start(),va_arg(),va_end() 详细解析

    va_list(),va_start(),va_arg(),va_end() 详细解析

    这些宏定义在stdarg.h中,所以用到可变参数的程序应该包含这个头文件.下面我们写一个简单的可变参数的函数,该函数至少有一个整数参数,第二个参数也是整数,是可选的.函数只是打印这两个参数的值
    2013-09-09
  • C++11新特性之右值引用与完美转发详解

    C++11新特性之右值引用与完美转发详解

    C++11标准为C++引入右值引用语法的同时,还解决了一个短板,即使用简单的方式即可在函数模板中实现参数的完美转发。本文就来讲讲二者的应用,需要的可以参考一下
    2022-09-09
  • Qt编写地图实现闪烁点图的示例代码

    Qt编写地图实现闪烁点图的示例代码

    闪烁点图的核心有三个要素,城市的名称、城市的经纬度、对应值的大小,当值越大闪烁点也就越大,本文就来实现一下地图闪烁点图,具有一定的参考价值,感兴趣的可以了解一下
    2021-12-12
  • C++实现静态链表

    C++实现静态链表

    这篇文章主要为大家详细介绍了C++实现静态链表,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • C++类与对象之运算符重载详解

    C++类与对象之运算符重载详解

    运算符重载的方法是定义一个重载运算符的函数,在需要执行被重载的运算符时,系统就自动调用该函数,以实现相应的运算。也就是说,运算符重载是通过定义函数实现的
    2021-10-10

最新评论