C++进阶学习(一) 默认参数、成员指针

news/2023/6/7 23:52:40

一. 默认参数

  • 函数参数出现缺省参数,位于后面的参数缺省参数必须已被声明

void func1(int, int, int = 10);
void func1(int, int = 6, int);
void func1(int = 4, int, int);void func1(int a, int b, int c)
{cout << a << " " << b << " " << c << endl;
}void func2(int a = 4, int b = 6)
{cout << a << " " << b << endl;
}int main()
{cout << "---begin---" << endl;func1();func2();cout << "---end---" << endl;return 0;
}

输出结果:

---begin---
4 6 10
4 6
---end---

这种书写方式同样可以应用于类的成员函数中,在类内声明时缺省靠后的参数,在类外实现时缺省靠前的参数

class Test
{
public:Test(int, int = 4);
};Test::Test(int a = 3, int b)
{cout << a << " " << b << endl;
}int main()
{cout << "---begin---" << endl;Test();cout << "---end---" << endl;return 0;
}

输出结果:

---begin---
3 4
---end---

  • 如果类外的默认参数会使非默认构造函数变为默认构造函数,则程序非良构,应尽量避免这种写法

class Test
{
public:Test(int); // 非默认构造
};Test::Test(int a = 3){} // 缺省后变为默认构造

  • 同时,默认参数应避免类内类外重定义

class Test
{
public:Test(int = 4); 
};Test::Test(int a = 3) {} 

  • 当类实现多态时,子类覆盖函数的默认参数会根据对象的静态类型确定

class Animal
{
public:virtual void func(int a = 1){cout << "Animal : " << a << endl;}
};class Cat : public Animal
{
public:void func(int a = 3) override{cout << "Cat : " << a << endl;}
};int main()
{cout << "---begin---" << endl;unique_ptr<Animal> ptr1{new Cat()};ptr1->func();unique_ptr<Cat> ptr2{new Cat()};ptr2->func();cout << "---end---" << endl;return 0;
}

输出结果:

---begin---
Cat : 1
Cat : 3
---end---

对程序进行编译分析时所得到的的表达式类型称为表达式的静态类型,程序执行过程中静态类型将不会改变,在上面的实例中ptr1的静态类型为Animal,动态类型为Cat,而ptr2的静态类型与动态类型都为Cat,故两者调用func时的默认参数不相同。


  • 函数的缺省值不能通过非静态成员变量进行赋值,但静态成员变量可以

class Test
{const int n = 3;static int t;public:// Test(int a = n); 无法通过非静态成员变量赋值Test(int a = t){cout << a << endl;}
};int Test::t = 4;int main()
{cout << "---begin---" << endl;Test();cout << "---end---" << endl;return 0;
}

输出结果:

---begin---
4
---end---

二、成员指针

  • 数据成员指针或虚函数成员指针不会指向一个内存,而是存储在该类中的偏移地址

  • 成员指针会指向特定的内存,但不能脱离实例对象使用

  • 成员函数指针在声明时需要加上作用域,由实例对象进行调用

class Test
{
public:void func(int a){cout << a << endl;}
};int main()
{cout << "---begin---" << endl;void (Test::*print)(int) = &Test::func;Test test, *test_ptr = &test;(test.*print)(5);(test_ptr->*print)(6);cout << "---end---" << endl;return 0;
}

输出结果:

---begin---
5
6
---end---

同样,函数指针也可以作为函数参数

class Test
{
public:void func(int a){cout << a << endl;}
};void run_func(void (Test::*p)(int), Test &test)
{(test.*p)(1);
}int main()
{cout << "---begin---" << endl;Test test;run_func(&Test::func, test);cout << "---end---" << endl;return 0;
}

  • 当函数指针作为函数参数时,若存在多个匹配的重载函数时,应使用static_cast来制定调用的函数类型

class Test
{
public:void func(){cout << "void" << endl;}void func(int a){cout << a << endl;}
};void run_func(void (Test::*p)(int), Test &test)
{(test.*p)(1);
}void run_func(void (Test::*p)(void), Test &test)
{(test.*p)();
}int main()
{cout << "---begin---" << endl;Test test;// run_func(&Test::func, test); 存在多个匹配的对象,无法确定调用哪一个run_func(static_cast<void (Test::*)(void)>(&Test::func), test);run_func(static_cast<void (Test::*)(int)>(&Test::func), test);cout << "---end---" << endl;return 0;
}

  • 在C++17之后,我们可以使用<functional.h>库中的invoke直接对成员变量与对象进行绑定:当传入数据成员指针时,将会得到一个与对象绑定的引用变量;当传入函数成员指针时,将会对特定对象直接调用该函数

class Test
{
public:int a = 1;void func(){cout << "void" << endl;}
};void run_func(void (Test::*p)(int), Test &test)
{(test.*p)(1);
}int main()
{cout << "---begin---" << endl;Test test;int &num = invoke(&Test::a, &test);num++;cout << test.a << endl;invoke(&Test::func, test);cout << "---end---" << endl;return 0;
}

输出结果:

---begin---
2
void
---end---

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.exyb.cn/news/show-4562696.html

如若内容造成侵权/违法违规/事实不符,请联系郑州代理记账网进行投诉反馈,一经查实,立即删除!

相关文章

文件锁定.

文件锁定是多用户、多任务操作系统中一个非常重要的组成部分。程序经常需要共享数据&#xff0c;而这通常是通过文件来实现的。因此&#xff0c;对于这些程序来说&#xff0c;建立某种控制文件的方式就非常重要了。只有这样&#xff0c;文件才可以通过一种安全的方式更新&#…

三、命令行工具cmder的安装

1、cmder安装 1.1、cmder简介 cmder是一个增强型命令工具&#xff0c;不仅可以使用Windows下的所有命令&#xff0c;并且还可以使用Linux和shell命令。 1.2、cmder下载 (1)cmder的官方网站提供的下载地址实在是太慢了基本是下载不下来&#xff0c;建议到清华大学的镜像站去…

阿里云服务器如何创建快照?

阿里云服务器如何创建快照&#xff1f; 首先我们来说一下什么是快照&#xff1f; 快照相当于是数据备份&#xff0c;可以为所有类型的ECS云盘创建快照&#xff0c;用于备份或者恢复云盘的数据&#xff0c;是一种高效的数据容灾手段。 我们可以为服务器的云盘创建快照&#x…

阿里云国际站云服务器可以用来做什么业务?

阿里云国际站的云服务器很受欢迎&#xff0c;因为国际版的云服务器搭建网站可以不用备案就可以上线业务。现在在互联网上一些常用的软件都是接住了云服务器上部署的的&#xff0c;比如微信、QQ、优酷视频、淘宝等&#xff0c;除此之外还有很多网站博客都是在云服务器上部署的&a…

一阶高通滤波器学习

导读&#xff1a;本期文章主要介绍一阶高通滤波器。一阶高通滤波器与一阶低通滤波器很相似&#xff0c;都是利用电容阻低频信号通高频信号&#xff0c;电感阻高频信号通低频信号的特点。一、一阶高通滤波器介绍滤波器是作为一种选频装置&#xff0c;是信号处理中的一个重要的概…

C++的继承,封装,多态

C是面向对象的语言&#xff0c;因此他和JAVA一样有面向对象语言的三大基本特征&#xff1a;封装&#xff0c;继承&#xff0c;多态。 封装&#xff1a;封装字面意思就是打包&#xff0c;包装起来&#xff0c;看不见里面是啥。稍微专业点就是指按照信息屏蔽的原则&#xff0c;把…

Java的三大特性之封装、继承和多态详解

面向对象编程有三大特性&#xff1a;封装、继承、多态。 【1】封装 封装隐藏了类的内部实现机制&#xff0c;可以在不影响使用的情况下改变类的内部结构&#xff0c;同时也保护了数据。对外界而已它的内部细节是隐藏的&#xff0c;暴露给外界的只是它的访问方法。 对于封装而…

【c++ 封装、继承、多态】

文章目录面向对象的三个基本特征1. 封装2. 继承2.1 继承的三种实现方式3. 多态3.1 多态的俩种实现方式分析3.2 多态存在的三个必要条件3.3 C多态机制的实现&#xff1a;4. 动态绑定与多态4.1 什么是动态绑定4.2 动态绑定发生的条件&#xff1f;4.3 动态绑定的实际意义4.4 程序面…