一.this 指针
构造函数中 代表正在被构建的对象
成员函数中 代表谁调用这个函数 this这个
指针就指向谁
this 作为参数
this 作为返回值
二.类型和权限的关系
不使用这个类型的对象 去调用成员函数
成员函数(编译器默认给传递一个this指针)
class A{
public:
void show()const{
}
};
void _Z1A4showEv(A* a);
三.const 对象 和 const 函数
const 函数 必须是成员函数
const 对象只能调用const函数
非const对象 优先调用非const 函数 如果没有
则调用const 函数。
const 函数 和 非const 函数可以构成重载
const 函数 不能修改成员变量 但可以访问
const 函数不能调用非const 函数。
四.析构函数
~ 无参构造函数前
在对象销毁前 自动调用一次
语法上允许调用多次
当有堆内存时 自定义析构函数
class A{
int *parr;
public:
A(){
parr=new int[5];
}
~A(){
if(parr){
delete [] parr;
parr=NULL;
}
}
};
A * a=new A();
delete a;
五.new malloc delete free的区别
1.如果成员是类类型 则自动调用这个类型的
构造函数
2.自动处理类型转换
3.调用这个类型的构造函数
delete 释放对象前 调用析构函数
六.静态成员
静态成员属于整个类型 而不属于某个对象
静态成员变量必须在类外进行初始化
调用静态成员使用类名:: 不需要对象就可以
调用。
静态成员函数不能访问非静态成员。
所以如果想访问非静态成员 则需要传递对象
的指针。
/* 封装线程 */
class A{
int data;
public:
static void showA(A* a){
a->data
}
};
七.成员指针
a.成员变量的指针
成员变量的类型 类类型::*变量;
=&类类型::成员变量名;
对象.*成员指针名;
对象地址->*成员指针名;
成员变量指针实际上是一个地址偏移量。
b.成员函数指针
只比普通函数指针 多了一个类名::
void (Date::*funptr)();
赋值时注意取地址 负责编译器将翻译成
funptr=&Date::showYear;
静态函数。
通过对象调用时 注意加小括号
(对象.*指针名)();
(date.*funptr)();
--------------------------------
运算符重载
1.什么是运算符重载
就是函数的特殊表现形式。
2.分数
x/y 1/3 1/2
f1+f2 时 编译器的翻译规则
a.去Fraction 类定义中 找一个成员函数
Fraction operator+(Fraction f2);
b.没有成员函数 就去全局区找一个函数
Fraction operator+(Fraction f1,
Fraction f2);
成员和 全局都存在 只要编译能通过 优先
选择成员。
+ - * / > <
3.把一个分数输出到屏幕
Fraction f(1,3);
cout<<f;
ostream 成员函数 operator<<(Fraction f)
全局形式
流对象不能拷贝 不能加const修饰
ostream& operator<<(ostream& os,
const Fraction& f);
为了访问私有成员 引入友元函数的概念
友元函数就是获得访问类私有成员的全局函数
friend ostream& operator<<(ostream& os,
const Fraction& f);
4.二元运算符
L#R
从L对应的类型中找一个成员函数声明
operator#(R对象类型)
如果没有就去全局找
operator#(L对象类型,R对象类型);
class Integer{
int data;
public:
Integer(int data=0):data(data){}
};
让Integer这个类型支持 >> << + -
== >
能是成员 就用成员形式 不能是成员就考虑
全局(友元)
返回值 如果是基本类型 c++和c相同认为只读
返回值 是非基本类型 c++ 和c 不同
c认为只读 c++默认可以覆盖这个临时结果
如果不让覆盖就加const修饰。
int a=10;
int b=10;
if(a==b){}
char a[30]="hello";
char b[30]="hello";
if(a==b){}
a+b;
a,b都没有变化
a+=b;
a变 b不变
5.单目运算符
#R - ! ~
R# ++ --
#操作数
#R
a.编译器去R类型中找一个成员函数
operator#()
b.如果找不到 就去全局找
operator#(R对象类型);
R#
编译器需要通过哑元区分
a.编译器去R类型中找一个成员函数
operator#(int)
b.如果找不到 就去全局找
operator#(R对象类型,int);