C++面向对象的三大特性:封装、继承、多态。
封装:
1. 将属性和行为作为一个整体来表现一个事务,并加以权限来控制使用。
2.struct与class的唯一区别是默认访问权限不同(struct默认公共,class默认私有)
访问权限:
public(公共权限) | 类内可以访问 | 类外可以访问 |
protected(保护权限) | 类内可以访问 | 类外不可以访问(子可访问) |
private(私有权限) | 类内可以访问 | 类外不可以访问(子不可访问) |
----------------------------类的构造和类对象的使用-----------------------
class Circle{ //一个class一般为: class = 访问权限 + 属性 + 行为
public://公共权限
//属性
int r;
//行为
double calculateZC(){
return 2 * 3.14 * r;
}
};
struct Circle c;//构造对象
c.r = 10;//给属性赋值
c.calculateZC();//调用类行为
------------------------------------------------------------------------
-------------------------私有能可以对成员精细化权限-----------------------
class mesa{
public:
setname()\showname()
showage()
set_id()
private:
string name;//可读可写
int age;//只读
string id;//只写
};
------------------------------------------------------------------------
对象特性:
初始化和清理
1.构造函数(A):没有返回值,不用写void,只在初始化调用一次,如果有参数,可重载
2.析构函数(~A):没有返回值,不用写void,只在销毁前调用一次,没参数,不可重载
构造函数的分类:
按参数:有参构造、无参构造
按类型:普通构造、拷贝构造
Person p1;//调用默认构造函数
Person p1();//调用自定义构造,如果你没写构造函数,默认是函数声明
为了避免这个问题,最好用显示构造:
Person p1 = Person();//Person()如果会被构造,那么执行完就被销毁,因为他是匿名函数
拷贝构造:
PERSON(const PERSON &p){
age = p.age;
}
拷贝构造函数:
拷贝构造调用的时机:
1.使用一个创建好的对象来初始化新对象
2.值传递的方式给函数参数传值 void task(Person p)
3.值方式返回局部对象 return Person;
构造函数规则:
1. 创建一个类,不主动编写的情况下,C++编译器为每个函数至少都添加4个函数
(构造函数、析构函数、拷贝构造函数、operator=)
2. 如果我们写了有参构造函数,编译器不再提供无参构造
3. 如果我们写了拷贝构造函数,编译器不再提供其他构造函数
深拷贝与浅拷贝:
浅拷贝:如果是变量(有自己内存),就是在栈上创建临时的直接拷贝,拷贝完消除临时;如果是指针,那么相当于多指针将指向同一块内存,报错
深拷贝:为了解决浅拷贝的问题,直接new一个堆区新地址去存放值,不会出现交叉释放的问题
初始化列表:
构造函数():属性1(值1),属性2(值2)...{}
静态成员函数:
1、所有对象共享一个函数
2、静态成员函数只能访问成员变量(不创建对象也能访问:Person::func())
对象特性:
C++对象模型和this指针:
成员变量和成员指针分开存储:
class Person{
};//
Person p;//空对象占用1个字节,为了1.和其他空对象相区分2.保证对象的唯一性
class Person1{
int a; //除非静态成员变量在类对象之中,其他都存储在类对像之外
static int b;
void fun1(){}
void fun2(){}
};
Person1 l;//占用4个字节
this指针:
每一个非静态函数只会生成一份函数实例,也就是说多个同类型的对象会公用一块代码。
—————通过this指针去区分对象调用自己
性质:
this指针是隐含每一个非静态成员函数内的一个指针;
this指针不需要定义,直接使用即可;
用途:
当形参和成员变量同名时,可以用this指针区分
在类的非静态成员函数返回对象本身,可以用return *this;
class Person{
public:
Person(int age){
this->age = age;//this指向的是被调用成员函数的对象
}
Person& add(int age){//不用引用,会调用拷贝函数重新生成一个临时变量
this->age += age;
return *this;
}
int age;
};
Person p;//这里this就是p调用,所以this指向p的age
空指针来调用成员函数:
class Person{
public:
void showclassname(){
if(this == NULL){
return ;
} //防止NULL调用成员函数报错
cout<<1;
}
void shownameage(){
if(this == NULL){
return ;
} //防止NULL调用成员函数报错
cout<<m_age;//默认为this->m_age;
}
int m_age;
};
Person *p = NULL;
p->showclassname();//正确
p->shownameage();//错误
const修饰成员函数:
常函数:
*成员函数后加const后我们称这个函数为常函数
*常函数内不可以修改成员属性
*成员属性声明加关键字mutable后,在常函数中依然可以修改
常对象:
*声明对象前加const称该对象为常对象
*常对象只能调用常函数
class Person{
void showPerson()const{// Person * const this;this被修改成指针常量,this不能被修改
//a = 0;
this->a = 0; //可
}
int a;
mutable int b;//常对象和常函数都可以修改他
};
const Person l;//此时a不能被修改,而b仍能被修改