C++复合类型
结构体
C++的结构,定义结构体类型的变量时,可以省略struct关键字
可以定义成员函数,在结构体中的成员函数内部可以直接访问本结构体的成员,无需通过"."或"->"
联合
C++的联合,定义联合体类型的变量时,可以省略union关键字
支持匿名联合
重点:共用一块内存空间
枚举
C++的枚举,定义枚举型的变量时,可以省略enum关键字
独立的类型,和整型之间不能隐式转换.
代码演示
cpp
#include<iostream>
#include<cstring>
using namespace std;
void testStruct(){
struct Student{
int m_age;
char m_name[128];
void getInfo(){
cout << m_name << ":" << m_age << endl;
}
};
/*struct*/ Student s1;
s1.m_age = 18;
strcpy(s1.m_name, "林枫");
s1.getInfo();
cout << "姓名:" << s1.m_name << ", 年龄:" << s1.m_age << endl;
}
void testUnion(){
union /*A*/{//匿名联合主要想体现 成员的内存排布方式(共用同一块内存空间)
int i;
char c[4];
};
//Union A a; //C语言写法
//A a; //C++写法
i = 0x12345678;
//cout << c[0] << ' ' << c[1] << ' ' << c[2]
// << ' ' << c[3] << endl;//输出对应字符
cout << hex << (int)c[0] << ' ' << (int)c[1] << ' ' << (int)c[2]
<< ' ' << (int)c[3] << endl;
}
void testEnum(){
enum Color{ red,green,blue };
//C语言写法
//enum Color c = red// 0-err//枚举类型不支持隐式转换
//C++写法
Color c = red;
Color d = green;
Color e = blue;
cout << "c = " << c << endl;
cout << "d = " << d << endl;
cout << "e = " << e << endl;
}
void testBool(){
bool a = true;//"";"fddgd"
bool b = false;"0.0000";"123";NULL;
cout << "a = " << a << ", b = " << b << endl;
cout << boolalpha << "a = " << a << ", b = " << b << endl;
}
int main(){
testStruct();
testUnion();
testEnum();
testBool();
return 0;
}
布尔类型
表示布尔量的数据类型
-->bool
布尔类型的字面值常量
-->true表示真 -->false表示假
布尔类型的本质 - 单字节整数
用1和0表示真和假
任何基本类型都可以被隐式转换为布尔类型
非0即真,0即假
代码演示
cpp
#include<iostream>
using namespace std;
void testBool(){
bool a = true;//"";"fddgd"
bool b = false;"0.0000";"123";NULL;
cout << "a = " << a << ", b = " << b << endl;
cout << boolalpha << "a = " << a << ", b = " << b << endl;
}
int main(){
testBool();
return 0;
}
函数关系--重载
重载关系
-->同一作用域内,函数名相同,参数表不同
-->根据实参类型和形参的类型进行匹配,调用最匹配的函数
-->只有同一作用域内的同名函数才涉及重载的关系,不同作用域的同名函数涉及的是隐藏关系。
重载解析
-->完全匹配>常量转换>升级转换>标准转换>自定义转换>省略号匹配
-->函数指针的类型决定其调用的重载函数的版本
重载关系
代码演示(重载匹配)
cpp
//重载关系: 1.同一作用域内 2.函数名相同 3.参数列表不同
//形参表是否相同,与参数名无关,与形参个数, 以及,每一个对应的参数类型有关
#include <iostream>
using namespace std;
void foo(char* c,short s){
cout << "1.foo" << endl;
}
void foo(int i,double d){
cout << "2.foo" << endl;
}
void foo(const char* c,short s){
cout << "3.foo" << endl;
}
void foo(double d,int i){
cout << "4.foo" << endl;
}
//int foo(double i,int d){} //错误,形参表相同,是否构成重载关系与返回值类型无关
int main(){
char* c;
short s;
foo(c,s);//1
const char* cc;//3
foo(cc,s);
int i;double d;
foo(d,i);//4
foo(i,d);//2
return 0;
}
代码演示(不同作用域下的重载关系)
cpp
//不同作用域的同名函数涉及的是隐藏关系
#include <iostream>
using namespace std;
namespace ns1{
void foo(char* c,short s){
cout << "1.foo" << endl;
}
void foo(int i,double d){
cout << "2.foo" << endl;
}
}
namespace ns2{
void foo(const char* c,short s){
cout << "3.foo" << endl;
}
void foo(double d,int i){
cout << "4.foo" << endl;
}
}
int main(){
using namespace ns1;//ns1中foo出现在可见表中
using ns2::foo;//ns2中foo出现在定义表中
char* c;
short s;
foo(c,s);//3
return 0;
}
重载解析
代码演示(重载解析优先级)
cpp
//重载解析优先级
#include<iostream>
using namespace std;
void foo(char* c, short s){ //完全匹配 _Z3fooPcs
cout << "1.foo" << endl;
}
void foo(const char*, short s){ //常量转换 _Z3fooPKcs
cout << "2.foo" << endl;
}
void foo(char* c, int s){
cout << "3.foo" << endl; //升级转换 _Z3fooPci
}
void foo(char* c, char s){ //标准转换 _Z3fooPcc
cout << "4.foo" << endl;
}
void foo(...){ //省略匹配 _Z3fooz
cout << "5.foo" << endl;
}
int main(){
char* c;
short s;
foo(c,s);//普通方式调用,由实参和形参的匹配度来决定调用哪个foo函数
void(*pfunc)(const char* c,short s) = foo;//_Z3fooPKcs
pfunc(c,s);//函数指针方式调用,由函数指针本身的类型决定调用哪个foo函数
return 0;
}
重载的本质--"换名机制"
Z --表示自定函数系统默认前缀
P --表示指针
c --char类型
s --short类型
K --const类型
z --表示可变长参数
屏蔽C++"换名机制"--extern "C"
通过****extern "C"可以要求C++编译器按照C方式编译函数,即不做换名
原函数
cpp
int sum(int a,int b){
return a + b;
}
int sub(int a, int b){
return a - b;
}
查看符号表
bash
tern$vi cal.cpp
11_extern$g++ -c cal.cpp
11_extern$ls
a.out cal.cpp cal.o libcal.a main.c main.o
11_extern$ar -r libcal.a cal.o
11_extern$nm libcal.a
cal.o:
0000000000000014 T _Z3subii
0000000000000000 T _Z3sumii
使用extern "C"
cpp
extern "C"{
int sum(int a,int b){
return a + b;
}
int sub(int a, int b){
return a - b;
}
}
查看符号表
bash
11_extern$g++ -c cal.cpp
11_extern$ls
a.out cal.cpp cal.o main.c main.o
11_extern$ar -r libcal.a cal.o
ar: 正在创建 libcal.a
11_extern$ls
a.out cal.cpp cal.o libcal.a main.c main.o
11_extern$nm libcal.a
cal.o:
0000000000000014 T sub
0000000000000000 T sum
11_extern$
缺省参数
1. 可以为函数的形参指定缺省(默认)值,当调用该函数时若未指定实参,则使用形参的缺省(默认)值。
2. 如果函数的某一个形参具有缺省(默认)值,那么该形参后面的所有形参必须都具有缺省(默认)值
3. 尽量避免因为使用缺省参数而导致重载匹配歧义
4. 函数形参的缺省(默认)值只能在函数声明中指定
cpp
//缺省(默认)参数:带默认值的形参
//默认值不是初始值
#include<iostream>
using namespace std;
void foo(int a, double b=3.14, float c=2.0, short d=1, char e = 'A');
void foo(int a){
}
void foo(int a, double b, float c, short d, char e) {
// 函数实现
cout << "e = " << e << endl;
}
int main(){
foo(1,2,3.0,4);
foo(1,2,3.0,4,'B');
//foo(10);//造成重载匹配歧义
return 0;
}