Day7类与对象 中
一、对象特性
1.1 空指针访问成员函数
#include<iostream>
using namespace std;
class student
{
int a=0;
public:
void print()
{
cout<<"不报错"<<endl;
}
void show()
{
// if(this==NULL) //防止出错
// {
// return;
// }
cout<<"报错"<<a<<endl;//等价于 this->a
}
};
int main()
{
student *p=NULL;
p->print();
//p->show();会报错因为空指针没有确定的对象访问不到属性,无中生有
system("pause");
}
1.2 const 修饰成员函数
- 常函数:成员函数加const后 void getname() const{};
-
常函数不可以修改成员属性
,相当于对于指针常量前面加上const:const student * const this;//值和指向都不能更改。除了一种情况:在成员属性前加关键字mutable:mutable int a;该值可改。
- 常对象:实例化对象时加上const;
-
常对象只能调用常函数
,不能修改属性除了在成员属性前加关键字mutable:mutable int a;可以修改属性
二、友元
- 定义:让类外特殊的一些函数或者类进行访问另一个类中的私有成员
- 关键字 friend;
2.1 全局函数做友元
#include<iostream>
using namespace std;
class student
{
friend void find(student &student);//作为友元访问私有成员。
private:
int name=0;
};
void find(student &student)//全局函数
{
cout<<student.name<<endl;
}
int main()
{
student s2;
find(s2);
system("pause");
}
2.2 友元类
#include<iostream>
using namespace std;
class student
{
friend class teacher;//友元类
private:
int name=0;
};
class teacher
{
public:
student s1;
void getname()
{
cout<<s1.name<<endl;//访问私有成员;
}
};
2.3成员函数做友元
#include<iostream>
using namespace std;
class student;
class teacher
{
public:
void getname();
void setname();
};
class student
{
friend void teacher::getname();//成员函数做友元
private:
int name=0;
};
void teacher::getname()
{
student s;
cout<<s.name<<endl;
}
int main()
{
teacher t;
t.getname();
system("pause");
}
- 访问的类应写在在被访问类之前,应写外部函数不然容易报错。
三、运算符重载
- 重新定义已有的运算符,实现另一种功能(自定义的数据类型)
3.1加号
- 实现两个自定义数据类型相加的运算
-
成员函数本质:s2=s.operator+(s1);
-
全局函数本质:s2=operator+(s,s1);
- 运算符重载可以实现函数的重载
class student
{
public:
int age=10;
student(int age)
{
this->age=age;
}
// student operator+(student &s1)//成员函数实现+号重载
// {
// student temp=0;
// temp.age=this->age+s1.age;
// return temp;
// }
};
student operator+(student &s,student &s1)//全局函数实现加号重载
{
student temp=0;
temp.age=s.age+s1.age;
return temp;
}
int main()
{
student s(10);
student s1=20;
student s2=s+s1;//自定义数据类型相加
cout<<s.age<<endl;
cout<<s1.age<<endl;
cout<<s2.age<<endl;
system("pause");
}
3.2左移(输出)
- 实现直接输出对象属性。
- 不用成员函数重载左移运算符,不能实现变量在右边。
- 重载返回值为ostream实现链式编程,实现追加输出。
- 使用友元输出私有成员属性。
class student
{
public:
int age=10;
char *name="张三";
student(int age)
{
this->age=age;
}
};
ostream& operator<<(ostream &cout,student &p)
{
cout<<p.name<<endl<<p.age<<endl;
return cout;
}
int main()
{
student s(10);
cout<<s<<endl;
system("pause");
}
3.3递增
-
前置递增返回引用
:实现一直对一个数据进行递增操作
后置递增返回值
- 使用占为参数区分前置和后期递增
3.4赋值
- C++编译器至少给一个类添加四个函数:
- 默认构造函数
- 默认析构函数
- 默认拷贝函数
- 赋值运算符 operator=,进行属性值拷贝。
- 解决浅拷贝重复释放堆区内存
- 返回值为自身(返回*this 引用)
class student
{
public:
int *num;
student(int age)
{
num=new int(age);//指针维护堆区
}
student& operator=(student &s)
{
if(num!=NULL)
{
delete num;
num=NULL;
}
num=new int(*s.num);//深拷贝
return *this;
}
};
ostream& operator<<(ostream &cout,student &p)
{
cout<<*p.num<<endl;
return cout;
}
int main()
{
student s(10);
student s1=20;
s1=s;
cout<<s1<<endl;
system("pause");
}
3.5函数调用运算符
class student
{
public:
int age;
student(int age)
{
}
void operator()(char * s)
{
cout<<s<<endl;
}
};
int main()
{
student s(10);
s("1234");
system("pause");
}