this
C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该指针去访问。
this指针的类型:类型 *const
只能在类的“成员函数”的内部使用
this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
类的6个默认成员函数
任何一个类在我们不写的情况下,都会自动生成下面6个默认成员函数。
- 构造函数主要完成类的初始化工作(实例化对象)构造函数可以重载
- 析构函数主要完成对象清理工作
- 拷贝构造函数是使用同类对象初始化创建对象
拷贝构造函数是构造函数的一个重载形式。
拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用。
编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了,在特定情况下,当类里面的成员变量包含有指针的时候,我们仍需自己实现,用于解决浅拷贝带来的内存多次问题。
成员函数不以引用(&)传递类对象参数将会调用拷贝构造函数- 赋值语句主要是把一个对象赋值给另一个对象
赋值运算符主要有四点:
参数类型
返回值
检测是否自己给自己赋值
返回*this
同样我们需要实现赋值语句,避免浅拷贝带来的问题。- 6.取地址重载,主要是普通对象和const对象取地址。
class Date
{
public :Date* operator&() //普通对象取地址重载{
return this ;}const Date* operator&()const //const对象取地址重载{
return this ;}
class Data
{
//构造Data(){
}//拷贝构造Data(const Date& d){
}};void main()
{
//如果用户显式定义了构造函数,编译器将不再生成默认构造函数Data d1; //无参构造函数,对象后面不跟括号,否则成为函数声明。Data d2 = d1;//Data d2(d1) 拷贝构造函数Data d3;d3 = d1; //赋值语句//声明了d3函数,该函数无参,返回一个日期类型的对象Date d3();
}
运算符重载
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
返回值类型 operator操作符(参数列表)
不能通过连接其他符号来创建新的操作符
用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不 能改变其含义
不能重载的运算符 ::(作用域限定符) sizeof, ?:(三目运算符), .(点号运算符)
const成员
const * 三种情况
- int const * p 封锁*p为常量,p指针指向的值为常量 *p不能改 p可以改
- int * const p p被修饰为常量,p不可以被更改, 但是*p可以更该 *p可以改 p不能改
- int const * const p和*p都不能被修改 *p 和 p 都不能改
void main()
{
int a = 4;int b = 10;//1.const int *p;int const *p;//2.int * const p = &a; //3.const int * const p = &a;
}void main()
{
const int a = 4;//int *p = &a; //错误const int *p = &a; //正确
}
class Date
{
public:void Display(){
cout << "Display ()" << endl;}void Display() const{
cout << "Display () const" << endl;//Date::Show(); const成员函数内不可以调用其它的非const成员函数。}void Set()const{
cout << "Set" << endl;}void Show(){
cout << "Show" << endl;Date::Set(); //非const成员函数内可以调用其它的const成员函数}void Get()const{
cout << "Get" << endl;}
};
void main()
{
Date d1;d1.Get();//非const对象可以调用const成员函数d1.Display();const Date d2; //const对象调用const成员函数d2.Display();
// d2.Show();//const对象不能调用非const成员函数
}
友元类和友元函数
友元提供了一种突破封装的方式,有时提供了便利。不宜多用
重载operator<<, operator>>友元使用较多友元函数
友元函数可访问类的私有和保护成员,但不是类的成员函数
友元函数不能用const修饰
友元函数可以在类定义的任何地方声明,不受类访问限定符限制
一个函数可以是多个类的友元函数
友元函数的调用与普通函数的调用和原理相同
友元类
友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
友元关系是单向的,不具有交换性。
友元关系不能传递
ostream& operator<<(ostream& cout, const Data& d)
{
cout<<d.val;return cout;
}
istream& operator>>(istream &in, Data& d)
{
in>>d.val;return in;
}
内部类
如果一个类定义在另一个类的内部,这个内部类就叫做内部类。
这个内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去调用内部类。
内部类就是外部类的友元类,但是外部类不是内部类的友元
内部类可以通过外部类的对象参数来访问外部类中
的所有成员。
注意内部类可以直接访问外部类中的static、枚举成员,不需要外部类的对象/类名
sizeof(外部类)=外部类,和内部类没有任何关系
static
用static修饰的成员变量,称之为静态成员变量, 静态的成员变量一定要在类外进行初始化,且所有对象共享。不属于任何一个对象。可以通过对象和类名调用
用static修饰的成员函数,称之为静态成员函数,只属于类,使用时必须用类名加作用域限定符和函数名调用。不包含this指针。不能访问非静态成员。
class A
{
public:static void show(){
cout << "show" << endl;/*get();*/ //静态函数无法调用非静态函数,由于没有this指针}void get(){
cout << "get" << endl;show(); //非静态函数可以调用静态函数}
};
内联函数
以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数提升程序运行的效率。
适用于短小精悍的代码 类似于宏 是一种声明 inline,对于有循环,递归的代码不适用于内联
内联函数 不能分离实现, 如 在一个文件声明 另一个文件实现, 是不可行的
宏的优缺点?
优点:
1.增强代码的复用性。
2.提高性能。
缺点:
1.不方便调试宏。(因为预编译阶段进行了替换), 严格的替换
2.导致代码可读性差,可维护性差,容易误用。
3.没有类型安全的检查 。
C++有哪些技术替代宏?
- 常量定义 换用const
- 函数定义 换用内联函数
explicit关键字
用explicit修饰构造函数,将会禁止单参构造函数的隐式转换。但是仍然可以显式转换。