浅拷贝与深拷贝
class Cat {
public:
string name;
Cat(string name) {
this->namr = name;
}
}
class Person {
public:
int age;
string name;
Cat cat;
Person(){}
Person(int age, string name, Cat cat) {
this->age = age;
this->name = name;
this->cat = cat;// 浅拷贝
}
Person(const Person& p) {
this->age = p.age;
this->name = p.name;
this->cat = p.cat;// 浅拷贝
// 解决下面方法
this->cat = new Cat(p.cat.name);
}
~Person() {
if(cat != nullptr) {
delete cat;
}
}
}
int main(){
Person p1(18, "小明", new Cat("宠物猫"));
Person p2 = p1;
delete p1;
delete p2;// 报错 因为在执行析构函数 释放cat 时 cat指向的空间不存在
return 0;
}
this
实现连续调用
class Number{
public:
int n;
Number(){}
Number(int n):n(n){}
Number& add(int a) {
this-> n += a;
return *this;
}
Number& subminus(int a) {
this->n -= a;
return *this;
}
};
int main(){
Number n1(10);
n1.add(9).subminus(1);// 打印18
cout<<n1.n<<endl;
return 0;
}
空指针
- 空指针可以调用成员函数,但是要求这个函数里面不包含this指针指向的成员变量
class Number{
public:
int n;
fun1() {
cout<<"fun1被调用了"<<endl;
}
fun2() {
cout<<this->n<<endl;
cout<<"fun2被调用了"<<endl;
}
};
int main(){
Number n1 = nullptr;
n1.fun1();
// n1.fun2();// 报错 空指针不能调用里面有this关键字的函数
return 0;
}
常函数
- 特点:
- 常函数用const修饰, 常函数里面可以调用所有成员变量,但不能修改成员属性,常函数里面只能调用常函数不能调用普通函数
class Number{
public:
int n;
Number(){}
Number(int n) {
this-> n = n;
}
void testConstFun(int n) const{
// this-> n = n;
this(n);
// cout<<n<<endl;
}
};
int main(){
Number n1;
n1.testConstFun(10);//报错 这个常函数里面调用了普通函数
return 0;
}
常对象
- 特点:
- 被const修饰,不能调用非常函数,不能修改成员属性的值
class Person {
public:
string name;
int age;
Person(){}
Person(int age, string name): age(age), name(name){}
void constFun() const{}
void normalFun(){}
};
int main(){
const Person p1 = {18, "小红"};
p1.constFun();
p1.normalFun(); // 报错 不能调用普通函数
p1.name = "小华";
return 0;
}
mutable
class Person {
public:
string name;
mutable int age;
Person(){}
Person(int age, string name): age(age), name(name){}
void constFun() const{
this->age = 30;
}
};
int main(){
Person p1 = {18, "小红"};
p1.constFun();
cout<<p1.age<<endl;// 打印30
return 0;
}
友元函数
// 全局函数做友元
class Person {
friend void goodFirendComming();
public:
string name;
mutable int age;
Person(){}
Person(int age,string name):age(age),name(name){}
private:
gotoBed() {
cout<<"去睡觉啦"<<endl;
}
};
void goodFirendComming() {
cout<<"好朋友来啦"<<endl;
Person p1;
p1.gotoBed();// 访问Person的私有成员函数
}
int main(){
Person p1 = {18, "小红"};
goodFirendComming();
return 0;
}
// 类的成员函数友元
class GoodFriend{
public:
void visit();
};
class Home {
friend void GoodFriend::visit();
private:
toBedRoom() {
cout<<"去客厅"<<endl;
}
};
void GoodFriend::visit() {
Home home;
home.toBedRoom();
};
int main(){
GoodFriend goodfriend;
goodfriend.visit();
return 0;
}
// 将类作为友元
class GoodFriend{
public:
void visit();
};
class Home {
friend class GoodFriend;
private:
toBedRoom() {
cout<<"去客厅"<<endl;
}
};
void GoodFriend::visit() {
Home home;
home.toBedRoom();
};
int main(){
GoodFriend goodfriend;
goodfriend.visit();
return 0;
}
运算符重载
- 写法: operator加运算符
- 全局函数重载运算符时,一元运算符一个参数二元运算符两个参数。类的成员函数重载运算符时,一元运算符没有参数二元运算符一个参数(类本身作为一个运算对象)
// 自增 自减
class Person {
public :
int age;
string name;
bool operator==(const Person& p) {
return age == p.age && p.name == name;
}
// 前置运算符
Person operator++() {
age++;
return *this;
}
// 后置运算符
Person operator++(int) {
Person p2 = *this;
age++;
return p2;
}
};
int main(){
Person p1 = {18, "小红"};
Person p2 = {20, "小白"};
cout<<(p1==p2)<<endl;
cout<<(++p1).age<<endl;// 先自增再取值
cout<<(p1++).age<<endl;// 先取值再自增
cout<<p1.age<<endl;
return 0;
}
// 重载运算符 <<
class Person {
public :
int age;
string name;
Person(int age, string name):age(age), name(name){}
};
ostream& operator<<(ostream& os, Person& p) {
os<<"name = "<< p.name << " age = "<<p.age;
return os;
}
int main(){
Person p1 = {18, "小红"};
Person p2 = {20, "小白"};
cout<<p1<<","<< p2<<endl;
return 0;
}
封装、继承、多态
- 封装:广义 把功能相似的变量封装成一个对象。侠义:可以对类的变量添加访问修饰符,然后如果公有方法访问,增加代码的安全性、复用性、可读写。
- 继承 提高代码的复用性。拓展性
- c++父类可以被多个子类继承,子类也可以继承多个父类
- c++中没有supper关键字
- 子类可以继承除了构造函数和析构函数以外的所有函数和属性,但访问权限不同
- c++ 有三种继承方式public、protected、private,超过继承范围的降级为继承权限,默认为私有继承
class Person {
public :
int age;
string name;
Person(){}
Person(int age, string name):age(age), name(name){}
};
class Student:public Person {
public:
Student(int age, string name){
this->age = age;
this->name= name;
}
};
int main(){
Student stu = {18, "小红"};
cout<<stu.age<<stu.name<<endl;
return 0;
}