C++ 特性 -封装

编译器:redpanda Dev.cpp.6.7.5

目录

1.1类和对象

1.2封装-权限:

1.3利用public接口实现对私有权限内容的读写操作:

1.4对象的初始化与清理:

1.4.1构造函数的分类及其调用:

1.4.2 深拷贝与浅拷贝:

1.5 初始化列表:

2.1 静态成员

2.1.2 成员变量和成员函数是分开存储的

2.1.3  this 指针的作用

2.1.4 空指针调用成员函数

2.1.5 const 修饰成员函数

2.1.6全局函数作为友元,在类内声明全局函数并用friend 关键字代表他是友元

2.1.7类和对象做友元

2.1.8成员函数做友元


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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

litian355

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值