编译器:redpanda Dev.cpp.6.7.5
目录
2.1.6全局函数作为友元,在类内声明全局函数并用friend 关键字代表他是友元
1.1类和对象
封装属性和行为作为整体
class typename{
admission://public,protected,private;
属性:
.......
行为函数:
......
};
int main(){
typename .... //实例化instantiate
}
1.2封装-权限:
公共权限: public:成员类内可以访问,类外也可以访问
保护权限: protected:成员类内可以访问,类外不可以访问,儿子可以访问父亲中的保护权限内容。
私有权限 : private:成员雷内可以访问,类外不可以访问,儿子不可以访问父亲中的私有权限内容。C++类内不声明,默认权限是私有
#include<bits/stdc++.h>
using namespace std;
#define PI 3.14
class Person{
public:
string name;
protected :
string car;
private:
int password;
public:
void init(){
name="ULL_64";
car="bigG";
password=124324;
}
};
signed main(){
Person p1;
p1.init();
cout<<p1.name<<endl;
//cout<<p1.car<<endl;//protected error
//cout<<p1.password<<endl;//protected error
return 0;
}
1.3利用public接口实现对私有权限内容得读写操作:
成员函数设置为私有的优点
1>可以自行控制读写权限;
2>对于写可以检测数据的有效性。
#include<bits/stdc++.h>
using namespace std;
#define PI 3.14
class Person{
public :
setname(string s){
name=s;
}
string getname(){
return name;
}
int getage(){
return age;
}
string getlover(){
return lover;
}
void setage(int x){
if(x<0||x>150)
{
cout<<"你这个老妖精!"<<endl;
return ;
}
age=x;
}
void setlover(string s){
lover=s;
}
private:
string name;
int age;
string lover;
};
signed main(){
Person p1;
p1.setname("EX艾雷王!");
p1.setage(1000);
p1.setlover("EX雷德王!");
cout<<p1.getname()<<endl;
cout<<p1.getage()<<endl;
cout<<p1.getlover()<<endl;
return 0;
}
1.4对象的初始化与清理:
构造函数与析构函数
构造函数的作用:初始化;
1.没有返回值不用写void
2.函数名与类名相同
3.构造函数可以有函数,可以发生重载
4.创建对象时,构造函数会自动调用一次。
析构函数:主要作用于对象被销毁前系统自动调用,执行一些清理工作。
1.没有返回值,不写void
2.函数名和类名相同,名称前加上~
3.析构函数不含参数,不可以发生重载
4.对象销毁前自动调用一次。
#include<bits/stdc++.h>
using namespace std;
class Person{
public:
Person(){
cout<<"构造函数的调用 "<<endl;
}
~Person(){
cout<<"析构函数的调用"<<endl;
}
};
void test01(){
Person p;
}
signed main(){
Person p;
test01();
system("pause");return 0;
}
1.4.1构造函数的分类及其调用:
按参数:含参构造,无参构造。无参构造函数不要写括号,会被编译器认定为非类的函数。
拷贝构造函数和普通构造。
注意:匿名对象的特点,当前执行结束后就被系统释放
括号法构造
Person p1;
Person p2(10);
Person p3(p2);
显示法构造:
Person p1
Person p2=Person(10)
Person p3=Person(p2);
注意:不要用拷贝函数初始化匿名对象。
隐式转化法
Person p1=10;
Person p2=p1;
拷贝构造的调用时机:
+ 使用一个已经创建完毕的对象来初始化一个新对象
+ 值传递的方式给函数参数传值
+ 以值的方式返回局部变量
构造函数调用规则:
1.1 编译器的默认构造函数
1.默认构造函数(无参空函数体)
2.默认析构函数(无参,函数体为空)
3.默认拷贝构造函数(对属性进行值拷贝)
1.2 注意事项
1.如果创建了有参构造函数,编译器就不再提供默认无参构造函数。
2.如果创建了拷贝构造函数,编译器就不再提供任何默认构造函数。
1.4.2 深拷贝与浅拷贝:
浅拷贝:简单的赋值拷贝参数,编译器进行逐个字节拷贝的是浅拷贝。
浅拷贝带来的问题是堆区的内存被重复释放
解决办法,重新写一个拷贝构造函数。
#include<bits/stdc++.h>
using namespace std;
class Person{
public :
int age;
int *height;
Person(){
cout<<"默认构造函数"<<endl;
}
Person(int x,int Height){
age=x;
height=new int (Height);
cout<<"有参构造函数"<<endl;
}
~Person(){
if(height!=NULL){
delete height;
height=NULL;
}
cout<<"析构函数"<<endl;
}
Person(const Person &p){
cout<<"copy"<<endl;
age=p.age;
height=new int (*p.height);
}
};
void test01(){
Person p1(10,135);
Person p2(p1);
cout<<p1.age<<" "<<p2.age<<endl;
cout<<*p1.height<<" "<<*p2.height<<endl;
}
signed main(){
test01();
return 0;
}
如果属性有在堆区开辟的,一定要自己实现一个拷贝构造函数。避免程序崩溃。
深拷贝:在堆去申请空间,进行拷贝操作
1.5 初始化列表:
语法:构造函数()属性1(val1) 属性2(val2).......{}
类内定义Person(int a,int b,int c) : m_a(a),m_b(b),m_c(c){}
类外调用Person p(30,20,10);
1.6类对象作为类成员
C++中类的成员可以是另一个类的对象,我们称该成员为类对象。
当其他的类的对象作为本类成员,先构造其他类的对象在构造本类成员。
析构是结论相反。
#include<bits/stdc++.h>
using namespace std;
class Phone{
public:
string phonename;
Phone(string name){
cout<<"Phone 的构造函数"<<endl;
phonename=name;
}
};
class Person{
public:
string name;
Phone phone;
Person (string Name,string Phonename):name(Name),phone(Phonename){
cout<<"Person 的构造函数"<<endl;
}
};
void test01(){
Person p("张三","iphone");
cout<<p.name<<" take an"<<p.phone.phonename<<endl;
}
signed main(){
test01();
return 0;
}
2.1 静态成员
静态成员就是再成员变量或成员函数的前面加上static 关键字,成为静态变两
静态成员分为:
+ 静态成员变量
1. 所有对象共享一份数据
2.在编译阶段分配内存
3.类内声明,类外初始化
+静态成员函数
1.所有对象共享一个函数
2.静态成员函数只能访问静态成员变量
#include<bits/stdc++.h>
using namespace std;
//静态成员函数:
//所有对象 共享同一个函数,公用所有成员变量,数据是共享的。
class Person{
public:
static void func(){
m_A=100000;//静态成员函数可以访问静态成员变量
// m_B=100;//error 静态成员函数不能访问非静态成员变量
cout<<"静态成员函数的调用..."<<endl;
cout<<m_A<<endl;
}
static int m_A;
int m_B;//非静态成员变量
private :
static void func2(){
cout<<"静态成员函数func2 的调用"<<endl;
}
};
int Person::m_A=100;//静态成员变量的的类外初始化
void test01(){
Person p1;
p1.func();//通过创建对象调用静态成员函数
Person::func();//通过类名直接调用:直接再Person作用域下调用静态成员函数。
//Person::func2(); error 静态成员函数是有访问权限的,func2是私有的静态成员函数
}
signed main(){
test01();
return 0;
}
2.1.2 成员变量和成员函数是分开存储的
特性 1.只有非静态成员变量才作用再类的对象上,是类的对象上一个特有的属性
特性2.为了区分空对象占用内存的位置,每个空对象被C++编译器分配了一个字节的内存。
特性3.当类内有非静态成员变量时,以该变量的数据类型分配空间。
#include<bits/stdc++.h>
using namespace std;
class Person{
public:
Person(){
ma=0;
}
int ma;
static int mb;//静态成员变量 不属于类的对象上
static void func() //静态成员函数 不属于类的对象上
{
mb=1000;
cout<<"静态成员函数的调用,静态成员变量mb=="<<mb<<endl;
}
};
//成员变量和成员函数是分开存储的,
//只有非静态成员变量才是属于类的对象上的,是类的对象上的特有的属性
class cube{
public :
int a;
};
class blank{
// 空对象。
};
signed main(){
blank p1;
//为了区分空对象占用内存的位置,每个空对象被C++编译器分配了一个字节的内存。
cout<<"sizeof p1==" <<sizeof (p1)<<endl;//sizeof p1 ==1,空对象占用内存为1字节
cube p2;
cout<<"sizeof p2=="<<sizeof (p2)<<endl;//sizeof p2==4,这时内存按照int a 的类型来存储
Person p3;
cout<<"sizeof p3=="<<sizeof (p3)<<endl;//sizeof p3==4,只有非静态成员变量才属于类的对象上
return 0;
}
2.1.3 this 指针的作用
1>解决名称冲突问题
2>this指针指向被调用函数的对象也就是一个返回自身的指针。
#include<bits/stdc++.h>
using namespace std;
class Person{
public:
//1.解决名称冲突问题
Person (int age,string name,string lover){
m_age=age;// 或者 this->m_age=age;
m_lover=lover;//this->m_lover=lover
m_name=name;//this->m_name=name
}
//2.this指针指向自身。指向被调用的成员函数所属的对象
Person & add(Person &p){
//p1.m_age+=p.m_age
this->m_age+=p.m_age;
return *this;
}
int m_age;
string m_name;
string m_lover;
};
void test01(){
Person p1(18,"ULL_64","myself");
p1.add(p1).add(p1);
cout<<p1.m_age<<endl<<p1.m_name<<endl<<p1.m_lover<<endl;
}
signed main(){
test01();
return 0;
}
2.1.4 空指针调用成员函数
隐藏在每个成员函数的内部都有一个this指针,this指针的本质是指针常量,是不允许修改的,
this:::: Person * const this
if(this==NULL) return ;//增强代码健壮性,防止空指针出错
利用this指针增强代码健壮性,防止传入空指针时引发错误。
2.1.5 const 修饰成员函数
常函数
1>成员函数加上const后称之为常函数。
2>常函数内不可以修改成员属性
3>成员属性声明时加上mutable 后在场函数中依然可以修改
常对象
1>声明对象前加const 称该对象为常函数
2>常对象只能调用常函数
#include<bits/stdc++.h>
using namespace std;
//常函数
class Person{
public:
int m_a;
mutable int m_b;
Person (int age){
m_a=age;
}
void show()const//常函数
{
// m_a=100;不合法的操作,原因,常函数是不能修改类的属性的
// this->m_a=100;//不合法的操作,this指针的本质是指针常量 相当于const Person *const this的指向不可修改
m_b=100;//it makes sense since m_b is mutable and special
cout<<m_b<<endl;
}
void try(){
cout<<"just try"<<endl;
}
};
//常对象 本身不允许修改属性
void test02(){
const Person p1(100);
//p1.m_a=100;//no p 无法被修改
p1.m_b=1000;//ok m_b is mutable
p1.show();//常对象只允许使用常函数
p1.try();//no 使用非常函数会改变成员对象的属性,因此不被允许。
}
signed main(){
test02();
return 0;
}
2.1.6全局函数作为友元,在类内声明全局函数并用friend 关键字代表他是友元
#include<bits/stdc++.h>
using namespace std;
// 友元 关键字 friend
// 全局函数作为友元,再类内声明全局函数并用friend 关键字代表他是友元
class building {
friend string goodguy(building &p);//告诉编译器goodguy 全局函数做友元
public :
string m_sittingroom="客厅";
private:
string m_bedroom="卧室";
};
string goodguy(building &p){
cout<<"your friend is trying to get your privacy"<<endl;
return p.m_bedroom;
}
void test01(){
building p1;
cout<<goodguy(p1)<<endl;
}
signed main(){
test01();
return 0;
}
2.1.7类和对象做友元
#include<bits/stdc++.h>
using namespace std;
// 类和对象做友元,友元可以访问自己私有成员
class Building;
class Goodguy;
class Building {
friend class Goodguy;
public:
Building ();
string m_sittingroom;
private:
string m_bedroom;
};
class Goodguy{
public:
Goodguy();
void visit();
Building *building;
//goodguy has a good friend which is building ,point *building point to it
};
Goodguy::Goodguy(){
building= new Building ;//building=(Building*)malloc(sizeof (Building ))
}
Building::Building()
{
m_sittingroom="客厅";
m_bedroom="卧室";
}
void Goodguy::visit(){
cout<<"your friend class is trying to get your privacy"<<endl;
cout<<building->m_bedroom<<endl;
}
void test01(){
Goodguy gg;
gg.visit();
}
signed main(){
test01();
return 0;
}
2.1.8成员函数做友元
#include<bits/stdc++.h>
using namespace std;
// 类和对象做友元,友元可以访问自己私有成员
class Building;
// 让visit1()可以访问类内的私有成员
// 让visit2()不可以访问类内私有的成员
class Goodguy{
public:
Goodguy();
void visit();
void visit1();
Building *building ;
};
class Building {
friend void Goodguy::visit();
public:
Building ();
string m_sittingroom;
private:
string m_bedroom;
};
Goodguy::Goodguy()
{
building =new Building ;
}
Building::Building (){
m_sittingroom="客厅";
m_bedroom="卧室";
}
void Goodguy::visit(){
cout<<"your friend is trying to get your privacy"<<endl;
cout<<building->m_sittingroom<<endl;
}
void test01(){
Goodguy gg;
gg.visit();
}
signed main(){
test01();
return 0;
}