C++ 类和对象(一、封装)

C++面向对象的三大特征为:封装、继承、多态

封装

类和对象

class Circle{
public :
	//属性
	int m_r;
	//行为
	double calculateZC(){
		return 2*pi*m_r;
	}
}
int main(){
	Circle c1;
	c1.m_r =10;
	cout<< c1.calculateZC();
}

访问权限

  1. public 类内,类外都可以访问
  2. protected 类内可以访问,类外不可以访问 儿子可以访问父亲种保护的内容(与继承有关)
  3. private 类内可以访问,类外不可以访问
class Person{
public:
	string m_Name;
proteceted:
	string m_Car;
private:
	int m_Password;
public :
	void func(){
	
	}
}

struct 和class的区别

class默认权限是private
struct默认权限是public

私有化的好处

  1. 自己控制读写权限(通过是否存在set和get函数)
  2. 对于写可以检测数据的有效性
    在这里使用c1和c2的&是为了防止再拷贝一份数据。

在这里插入图片描述

如何把类单独写一个文件

Point.h如下:

#pragma once
#include <iostream>
using namespace std;
class Point
{
private:
	int X;
	int Y;
public:
	int getX();
	int getY();
};

Point.cpp如下:
只写函数的具体实现即可。要加Point::命名空间

#include "Point.h"
int Point::getX() {
	return X;
}
int Point::getY() {
	return Y;
}

构造函数和析构函数

构造函数和析构函数
构造函数可以无参,也可以有参。可重载。

拷贝构造函数

Person(const Person &p){
	m_Age =p.age;
}

匿名对象 Person(10) 调用后会立刻被回收,因为没有给他名字。

使用时机
  1. 使用一个已经创建好的对象给新的对象传值。
  2. 实参传给形参的时候会调用拷贝构造函数
    在这里插入图片描述
  3. 值返回局部对象
Person doWord(){
	Person p1;
	return p1;
	//此时return 的不是p1,而是p1拷贝之后的副本。
}

构造函数调用规则

  1. 编译器添加三种函数:
  • 构造函数
  • 析构函数
  • 拷贝构造 (值拷贝)
  1. 如果提供了有参构造,那么编译器就不会提供默认的空构造。仍会提供拷贝构造。
  2. 如果提供拷贝构造,编译器不会提供无参构造

深拷贝和浅拷贝

析构函数作用:
将堆区开辟得数据做释放操作
编译器提供的拷贝构造函数,会做浅拷贝的操作。浅拷贝会使两个对象指向同一块堆区
浅拷贝带来的问题,堆区的内存重复释放。

解决办法

重写拷贝构造函数。

Person(const Person &p){
	m_Age = p.age;
	//m_height = p.height//这个是编译器默认的拷贝构造函数
	m_height = new int (*p.m+Height);
}

总结

如果属性有在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝带来的问题。

初始化列表属性

主要作用是赋初值
在这里插入图片描述
可以通过这个赋值

构造和析构顺序问题

当一个类的对象作为另一个类的成员是,顺序是怎么样的?
构造顺序:先构造类的对象,再构造自身。
析构顺序:析构的顺序和构造的顺序相反。

静态成员

静态成员函数
  • 所有对象共享一个函数
  • 静态成员函数只能访问静态成员变量
两种调用方法:

在这里插入图片描述
不需要创建对象也可以访问,因为所有对象共享一个函数。

为什么不可以访问非静态成员?因为函数是共享的,不可以区分变量是哪个对象的。

C++对象模型this指针。

空对象也会被分配一个字节的空间.空对象也需要区分。

class Person{
}

Person p;
sizeof(p)//结果为1

如果不是空的。就看类里面的就可以。

class Person{
	int m_A;
	static int m_b;//不属于类的对象里面。
	void func(){}//非静态成员函数 不属于类的对象上
	static void func2(){}//静态成员函数,不属于类的对象上。
}

Person p;
sizeof(p)//结果为4
结论

只有非静态成员变量属于类的对象。(看对象的大小)

this作用
  1. 解决名称冲突
    this 指针指向 被调用的成员函数 所属的对象
class Person{
public:
	Person(int age){
		//age=age; //这里的age指的是形参,不会去修改类内的age
		this->age = age;
	}
private:
	int age;
}
  1. *this的使用
class Person{
public:
	Person(int age){
		//age=age; //这里的age指的是形参,不会去修改类内的age
		this->age = age;
	}
	Person & PersonAdd(Person p){//前面的引用一定要用,不然就是新的变量,p2` , p2``等,不可以链式的修改p2了。
		this->age += p.age;
		return *this;//此时this指向的是p2。*this可以返回p2。
	}
private:
	int age;
}

p2.PersonAdd(p1).PersonAdd(p1).PersonAdd(p1);

const修饰成员函数(常函数)

mutable的作用
成员函数后面加const,修饰的是this指向,让指针指向的也不可以修改。

void showPerson()const{
	m_A=100;//此行报错
	this->m_b = 100;//有mutable ,就可以修改了
}


int m_A;
mutable int m_B;

常对象

const Person p;
p.m_A=100;//此行报错
p.m_b = 100;//在类种属性声明时有mutable ,就可以修改了

常对象只能调用常函数。因为常对象不可以调用普通成员函数,因为普通的成员函数可以修改成员属性。

友元函数

正常情况不可访问类种的私有属性,友元函数可以访问。
共三种;

  • 全局函数做友元,(在类的开始加一个函数的friend声明)
  • 类做友元
全局函数做友元
class Building{
fried void visitRoom(Building *buidling);//全局函数做友元
public :
	string sittingRoom;
private:
	string bedRoom;
}


void visitRoom(Building *buidling){
	building->sittingRoom;
	building->bedRoom;//正常来说不行

}
类做友元

在类的开始的时候写
friend class Person;//此时perSon就可以访问Building类

class Building{
	friend class Person;
}
成员函数做友元

位置都是相同的, 需要加一个声明,在Person类里面的成员函数。

 friend void Person::visit();

运算符重载

全局函数:Person p3 = p1+p2;

Person operator+ (Person &p1,Person &p2){
	Person temp;
	temp.m_A = p1.m_A + p2.m+A;
	return temp;
}

成员函数:Person p3 = p1+p2;

Person operator+ (Person &p1){
	Person temp;
	temp.m_A = p1.m_A + this->m_A;
	return temp;
}

左移运算符重载

作用:可以自定义输出

只能利用全局函数重载左移运算符。
cout<<属于ostream中的一个对象。返回ostream对象可以实现链式调用。

ostream & operator<<(ostream&cout,Person &p){
	cout<<p.m_A<<p.m_b;
	return cout;
}

仿函数

class MyAdd{
public:
	int operator()(int num1,int num2){
		return num1+num2;
	}
}
MyAdd myadd;
myadd(1,2); 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值