文章目录
- 目录
- static静态成员
- static静态成员的访问
- static静态成员的定义和初始化
- 只能类内部声明使用,不能外部重复使用的关键字
- 类的隐式类型转换什么时候发生?有什么缺点?
- 类的隐式类型转换怎么阻止?
- 类的隐式类型转换阻止了再开启怎么办?
- 成员初始化的顺序是什么?
- 构造函数初始化完成在什么时候?
- 构造函数初始值什么情况下必须?
- 名字查找之成员声明
- 类的编译顺序是什么?
- 返回值什么时候要加上作用域::?
- 基于const的重载
- const成员函数失效,mutable
- inline函数怎么定义?
- 友元是什么?友元怎么声明?
- 类的用户访问友元怎么声明?
- 类的成员访问友元怎么声明?
- public和private的区别?
- class和struct的区别?
- 内联函数是什么?
- 非成员函数的声明在哪里?
- 作用域运算符在非成员函数上也用?
- 非const成员函数,可以被常量对象调用吗?
- const成员函数的const修饰什么?
- 成员函数内部要通过this->访问成员吗?
- 成员函数返回一个对象本身怎么写?返回拷贝(一个新对象)怎么写?
- this是什么?
- 成员函数和非成员函数的声明和定义的位置?
- 函数指针
- 函数指针做返回值
- const_cast和重载
- 函数重载,形参顶层const
- static
- cin\cout输入输出
- 输出字符串常量
- 循环读取输入
- nullptr和NULL的区别?
- 默认初始化
- 定义和声明的区别?
- 注意:extern的作用域
- 共享变量?extern?
- 引用
- 指针和引用的区别?
- 指针定义
- 解引用
- 空指针
- 指向指针的指针
- 指向指针的引用int*&
- const 对象必须初始化
- extern const
- 指向常量的引用
- 指向常量的指针
- 简记:*右const修饰指针
- 指向常量的指针(只读、指向可变)
- 常量指针(读写,指向不变)
- 顶层const,底层const
- 常量表达式
- constexpr 变量
- 声明constexpr用到的类型,字面值类型
- constexpr和const的区别?
- typedef 类型别名的两种方法
- auto
- decltype类型指示符
- 预处理器
- 范围for
- 什么时候不能用范围for?
- 迭代器怎么用?
- 显示类型转换
- 左值、右值
- 顺序容器
目录
static静态成员
类相关,共享与对象间的,不存在对象中的成员。
与对象无关就不能声明const静态函数。
static静态成员的访问
访问:
1.通过classname::
2.通过对象,指针,引用
static静态成员的定义和初始化
一般只能在类外部定义和初始化
只能类内部声明使用,不能外部重复使用的关键字
explicit,static
类的隐式类型转换什么时候发生?有什么缺点?
当构造函数只有一个形参时,可以用形参直接当对象用。
缺点:如果有成员函数的形参是类的引用,把形参A直接当对象用会发生,形参A变为类的临时量,用完就销毁了,不存在了。
类的隐式类型转换怎么阻止?
用explicit修饰构造函数,只能类内部声明
类的隐式类型转换阻止了再开启怎么办?
用static_cast()强制转换为类类型
成员初始化的顺序是什么?
不是初始化列表的顺序,而是类中出现的顺序。
构造函数初始化完成在什么时候?
构造函数函数体执行前
构造函数初始值什么情况下必须?
当成员是const,引用,某种没有定义默认构造函数的类时。
名字查找之成员声明
如果成员声明了类中不存在的类型,则在定义该类的作用域中继续找。
类的编译顺序是什么?
先编译成员的声明,再编译函数体。
返回值什么时候要加上作用域::?
类外部,第二个classname的作用域不包括返回值
classname::返回值 classname::function(){}
基于const的重载
类型一:一般用类型二,类型一有很多语句重复
class A{
public:
A &fun(){smallfun();return *this}
const A &fun()const{smallfun();return *this}
private:
smallfun()const{}//相同功能
};
类型二
const成员函数失效,mutable
成员数据加修饰mutable,就可以被const成员函数修改了
inline函数怎么定义?
class A{
private:
fun();//如果有定义则默认inline,此处只是声明,不是inline
};
inline fun(){
...}
友元是什么?友元怎么声明?
一种访问说明,类A外部的【类】或【函数】可以访问类A的private成员。
class A{
friend fun();//在此声明插件
}
类的用户访问友元怎么声明?
class A{
friend fun();
}
fun();//类外部还要再次声明
类的成员访问友元怎么声明?
extern fun();//类外部还要再次声明
class A{
friend fun();
private:
memfun(){fun();}//2.才能调用
}
public和private的区别?
- 修饰类内成员时,private修饰的只能类自己用,类外不能访问。
class和struct的区别?
默认访问说明符不一样,class默认private,struct默认public
内联函数是什么?
相当于宏定义,避免函数调用的开销。
非成员函数的声明在哪里?
非成员函数是插件,头文件是整个软件,类是软件主体。类外部,可以和类在一个头文件中。不用作用域运算符
头文件.h
[
类{};//注意有;
非成员函数声明;
]
作用域运算符在非成员函数上也用?
no,只有成员函数在类外定义时用
【返回值】【classname::funcname()】{函数体}
非const成员函数,可以被常量对象调用吗?
摘帽子怎么可以呢?this是定向的,也就是底层const,常量对象是顶层const。
const成员函数的const修饰什么?
修饰this,定向加只读。
object& memfunction() const{
return *this;
}
成员函数内部要通过this->访问成员吗?
不用显示写出来,直接可以写成员。
成员函数返回一个对象本身怎么写?返回拷贝(一个新对象)怎么写?
返回一个对象本身
object& memfunction(){
return *this;
}
返回拷贝
object memfunction(){
return *this;
}
this是什么?
object.mem();
在成员函数mem内部this就是一个定向(常量)指针,指向object。
成员函数和非成员函数的声明和定义的位置?
声明是一种身份归属,定义就是游戏MOD。
所以成员函数的声明在类内部,定义在内外都可以,可以是自带MOD,也可以是魔改MOD。非成员函数就是插件,定义声明都在外部。
函数指针
int(*p)(int,int);
p=fun;
函数指针做返回值
auto fun(int)->int(*)(int,int);
或者
using pf=int(*)(int,int);
pf fun(int);
const_cast和重载
用常量版本实现非常量版本,const_cast可以去掉const属性也可以加上
函数重载,形参顶层const
由于非const可以转换成const,也就是说可以加上顶层const,所以形参如果是有无顶层const的区别,则不能重载。
static
修饰函数内部的局部变量后,这个变量在函数外还有效,生命周期直到程序结束
cin\cout输入输出
#include<iostream>
int main(){
int v1 = 0, v2 = 0;
std::cin >> v1 >> v2;
std::cout <<"v1+v2="<< v1 + v2;//拼接输出用“<<”
return 0;
}
输出字符串常量
std::cout<<”wdadw”;
std::cout<<endl;//刷新缓冲区
不是标准库文件用include”xx.h”
循环读取输入
while (std::cin>>v1)
nullptr和NULL的区别?
nullptr是字面值;NULL是预处理变量。
默认初始化
内置类型:定义在函数体外,赋予默认值;定义在函数体内,是未定义的值。
类的对象:类决定。
定义和声明的区别?
声明:没有显示初始化
extern int i
定义:
- 无extern
- 或者有extern但是有显示初始化
注意:extern的作用域
- 函数体外部:extern int i=1;//定义
- 函数体内部:extern int i=1;//error
共享变量?extern?
不同文件中的变量的【定义和声明】都要加上extern
引用
字面值没有引用
引用分为:
- 左值引用:别名
int i=1;
int &d=i;
- 右值引用
指针和引用的区别?
指针是对象,引用不是。
指针定义
int i=2;
int *p=&i;
解引用
*p;//p是指针,*p是指针指向的内容
空指针
int *p= nullptr;//0也可以
指向指针的指针
int i=0;
int *p=&i;
int **p2=&p;
指向指针的引用int*&
int i=0;
int *p=&i;
int *&a=p;
const 对象必须初始化
extern const
不同文件可以共享
在test.cpp下
#include <iostream>
extern const int i=1;//提供给外部文件共享i
在main.cpp下
extern const int i;//声明这里要使用外部变量
cout<<i<<endl;//1
指向常量的引用
可以戴帽子
int i=1;
const int &i2=i;//不能通过i2改变i
不能脱帽子
const int i=1;
int &i2=i;
指向常量的指针
可以戴帽子,不可以摘帽子
总结:指向常量的指针/引用的共同点都是不能通过自己改变对方(指向的物)。
简记:*右const修饰指针
指向常量的指针(只读、指向可变)
*左const:修饰指针指向的物
const double pi=3.14;
//double *pa=π//指向变量的指针
const double *pb=π//指向常量的指针,不能脱帽子
double b=1.1;
pb=&b;//指向可变
常量指针(读写,指向不变)
*右const:修饰指针
int a,c=0;
int *const pa=&a;//指针功能:指向不变,读写
*pa=1;
// pa=&c;//error
const int b=0;
const int *const pb=&b;//指针功能:指向不变,只读
顶层const,底层const
顶层const:是常量
底层const:针对指针的,表示指针指向的物是常量
当同时存在有顶层或底层const的对象赋值时,只有有相同底层const的对象才能相互赋值。
常量表达式
常量表达式:编译期可得,如字面值,常量表达式初始化的const。
int i=1;//不是,1是,int 不是
constexpr 变量
可以修饰变量,表示变量是个常量表达式。
可以修饰函数,在编译时就能计算出结果。
声明constexpr用到的类型,字面值类型
如算术类型,引用,指针。但是自定义类,IO类,string都不是。
constexpr指针的初始值,必须为nullptr,0,固定地址。
但是函数体内部的变量地址不固定,所以不能指向那些变量。
函数体外的变量地址不变。
但是函数可以定义函数体外的一类变量,它们地址固定,可以指向它们。
constexpr和const的区别?
注意
int i=2;
int j=3;
int main()
{
constexpr int *p=&i;//顶层const,常量指针,读写,指向不变
constexpr const int *p2=&j;//常量指针+只读
return 0;
}
typedef 类型别名的两种方法
//1
typedef double wages;//wages=double
typedef wages base,*p;//base=double,p=double*
//2
using NMAE1=int;
//对于复合类型,如指针,
typedef char *pstring;
const pstring cstr=0;//不是简单的替换,而是一种修饰,const修饰pstring,cstr是常量指针
const pstring *ps;//ps是指针,指向一个对象(一个常量指针)
auto
//编译器确定类型,必须有初始值
//一般会忽略顶层const(指向不变),保留底层const
const int ci=i;//顶层const
auto b=ci;//b为int类型
//
//如果希望变为顶层const,可以这样定义
const auto b2=i;//b2是const int
//
const int i=1;
auto e=&i;//对常量取地址是底层const,所以e是const int *
//
auto &h=1;//error,不可以为普通引用绑定字面值
const auto &h=1;//可以为常量引用绑定字面值
decltype类型指示符
//
decltype(f()) sum =x;//f()可以是变量或是表达式
//
int i=42,*p=&i,&r=i;
//表达式
decltype(r+0) b;//r是int&,加0,b为int
//*
//*p可以被赋值,所以是左值,所以是int&
decltype(*p) c=i;//,*p是表达式,c是int&
//(())
decltype((i));//双()是引用,int&
decltype(i);//int
预处理器
确保头文件多次被包含,还可以正常运行
# ifndef xxx//如果不包含xxx就执行到endif
# include ...
# endif
范围for
改变字符,用引用
for (auto &c : s)
//...
cout << s << endl;
什么时候不能用范围for?
在循环体中向vector添加元素时不能用
迭代器怎么用?
定义:
vector<int> ::iterator it;
vector<int> ::const_iterator it;只读,叫常量迭代器
const vector<int> ::iterator it;定向
解引用:
*iter:返回元素的引用
iter->成员:相当于(*iter).成员
如果容器是常量,则迭代器只能用常量迭代器
显示类型转换
cast:铸造
搞这个说明设计程序有缺陷
运行时类型识别:dynamic_cast
通俗的类型转换,但是不能包含底层const:static_cast
改变const(摘或带帽子),函数重载大有用处:const_cast
看作是其他类型,并没有实际转换(开美颜了):reinterpret_cast
左值、右值
左值:用这个值的地址(家庭住址)
右值:用这个值的内容(人)
顺序容器
有反向迭代器
auto什么时候是const_iterator?
auto it=a.begin();// it的类型和a一致
auto it=a.cbegin();//const_iterator