您的位置:首页 > 娱乐 > 八卦 > 湖南长沙邮政编码_在线短链接生成网址_专业做网络推广的公司_网站整站优化

湖南长沙邮政编码_在线短链接生成网址_专业做网络推广的公司_网站整站优化

2024/12/23 22:56:54 来源:https://blog.csdn.net/qq_33582129/article/details/144363457  浏览:    关键词:湖南长沙邮政编码_在线短链接生成网址_专业做网络推广的公司_网站整站优化
湖南长沙邮政编码_在线短链接生成网址_专业做网络推广的公司_网站整站优化
c++面向对象的三大特性:封装、继承、多态
c++ 认为万事万物皆为对象,对象上有其属性和行为

1. 封装

1.1 封装的意义

1. 将属性和行为作为一个整体进行封装,表现生活中的事物
2. 将属性和行为加以权限控制
#include <iostream>
using namespace std;
# define PI 3.14
// 封装的意义
// 1. 将属性和行为作为一个整体进行封装,表现生活中的事物
// 2. 将属性和行为加以权限控制// 设计一个圆形工具类,求圆的周长和面积
class Circle{// 访问权限// 公共权限 public
public:// 1. 属性int m_r;// 2. 行为// 计算周长double calculateZC(){return 2 * PI * m_r;}
};int main(int argc, char const *argv[])
{// 通过圆形工具类创建圆形对象Circle c1;// 给圆形对象的半径赋值c1.m_r = 10;cout << "圆形的周长为:" << c1.calculateZC() << endl;return 0;
}
#include <iostream>
using namespace std;
# define PI 3.14// 设计一个学生类,属性有姓名、学号、年龄,行为有显示个人信息
class Student{// 类中的属性和行为都称为类的成员// 属性 和 行为 统称为成员// 属性 也称为成员属性,成员变量// 行为 也称为成员函数,成员方法public:string m_Name;int m_Id;int m_Age;// 显示个人信息void showStudentInfo(){cout << "姓名:" << m_Name << " 学号:" << m_Id << " 年龄:" << m_Age << endl;}// 给姓名赋值void setName(string name){this->m_Name = name;}
};int main(int argc, char const *argv[])
{// 创建学生对象Student s;// 给属性赋值s.m_Name = "张三";s.m_Id = 1;s.m_Age = 18;// 调用显示个人信息的函数s.showStudentInfo();s.setName("李四");s.showStudentInfo();return 0;
}

权限的分类

// 访问权限
1. 公有 public  成员类内外都可以访问
2. 私有 private 成员类内可以访问,类外不可以访问
3. 保护 protected 成员类内可以访问,类外不可以访问,子类可以访问
#include <iostream>
using namespace std;
# define PI 3.14class Person{public:// 公共权限string name;
protected:// 保护权限string car;
private:// 私有权限int m_Password;
public:void func(){name = "zhangsan";car = "玛莎拉蒂";m_Password = 123456;}
};int main(int argc, char const *argv[])
{Person p1;p1.name = "张三";// p1.car = "保时捷";  // 保护权限类外不可访问// p1.m_Password = 333333; // 私有权限类外不可访问return 0;
}

1.2 struct和class 区别

struct 和 class 的区别

默认权限不同
区别:
struct 默认权限是 public
class 默认权限是 private

#include <iostream>
using namespace std;
# define PI 3.14// struct 和 class 的区别
// 1. 默认权限不同
// 区别:
// struct 默认权限是 public
// class 默认权限是 privateclass C1{int m_A; // 默认权限是 private
};struct S1{int m_A; // 默认权限是 public
};int main(int argc, char const *argv[])
{C1 c1;// c1.m_A = 10; // 错误,访问失败S1 s1;s1.m_A = 10; // 正确,访问成功return 0;
}

1.3 成员属性设置为私有

#include <iostream>
using namespace std;
#include <string>// 成员属性设置为私有
// 优点1:可以自己控制读写权限
// 优点2:对于一些特殊数据,可以设计特殊的成员函数进行验证 即对于写权限,我们可以检测数据的有效性
class Person{
private:    string m_Name; //姓名 可读写权限int m_Age; //年龄 只读权限string m_Idol; //偶像 只写权限
public:void setName(string name){m_Name = name;}string getName(){return m_Name;}int getAge(){return m_Age;}void setIdol(string idol){m_Idol = idol;}};
int main(int argc, char const *argv[])
{Person p;p.setName("张三");cout << "name: " << p.getName() << endl;// 获取agecout << "age: " << p.getAge() << endl;// 只写权限p.setIdol("周杰伦");return 0;
}

2. 对象的初始化和清理

2.1构造函数和析构函数

// 构造函数 和 析构函数
// 对象的初始化和清理工作是编译器强制要求我们实现的,因此,如果我们不提供构造和析构,编译器会提供
// 编译起提供的构造函数和析构函数是空实现// 构造函数:主要用于创建对象时未对象的成员变量初始化,构造函数没有返回值,也不写void,构造函数可以有参数,可以发生重载,构造函数由编译器自动调用,无需手动调用,而且只会调用一次
// 析构函数:主要用于对象销毁前系统所做的清理工作,析构函数由编译器自动调用,无需手动调用,而且只会调用一次
#include <iostream>
using namespace std;
#include <string>
#include "point.h"
#include "cricle.h"class Person{public:Person(){cout << "Person构造函数" << endl;};Person(int age){cout << "Person构造函数" << age << endl;};// 析构函数 进行内存回收// 函数名称 类名称 后面加一个~ 然后括号里面写析构函数的参数~Person(){cout << "Person析构函数" << endl;}
};void test01(){Person p1; // 在栈上的数据,当函数执行完毕后,会自动调用析构函数,释放这个对象的内存
}int main(int argc, char const *argv[])
{test01();cout << "Hello World 11" << endl;return 0;
}

2.2 构造函数的分类及调用

// 构造函数的分类及调用
// 按参数分类分为 无参(默认), 有参
// 按类型分类分为 普通, 拷贝
// 三种构造函数的调用规则:
// 1. 如果用户定义有参构造函数, 那么编译器不会提供默认构造函数
// 括号法
// 显示法
// 隐式转换法
#include <iostream>
using namespace std;
#include <string>
#include "point.h"
#include "cricle.h"// 构造函数的分类及调用
// 按参数分类分为 无参(默认), 有参
// 按类型分类分为 普通, 拷贝
class Person{
public:    Person(){cout << "无参构造函数调用  " << endl;}Person(int a){this->age = a;cout << "有参构造函数调用  " << endl;}// 拷贝构造函数Person(const Person &p){cout << "拷贝构造函数调用  " << endl;// 如果数据属性比较多, 应该全部拷贝age = p.age;}~Person(){cout << "析构函数调用  " << endl;}int age;};// 调用
void test01(){// 1. 括号法// Person p1;  // 无参构造// Person p2(10); // 有参构造// Person p3(p2); // 拷贝构造// 注意事项:调用默认构造函数的情况, 不要加()// Person p4(); // 不加括号, 认为是函数声明, 不会认为是创建对象, 返回值类型为 Person// cout << "p2 的年龄为: " << p2.age << endl;// cout << "p3 的年龄为: " << p3.age << endl;// 2. 显示法Person p1;Person p2 = Person(10);Person p3 = Person(p2); // 拷贝构造p2.age = 100;p3 = p2; // 赋值操作, 就是把 p2 的值拷贝给 p3 , 不会调用拷贝构造函数, 会调用 赋值运算符重载函数,  如果没有赋值运算符重载函数, 会调用 拷贝构造函数, 如果没有拷贝构造函数, 会调用 默认构造函数,因为已经调用过了构造函数,所以不会再次调用cout << "p2 的年龄为: " << p2.age << endl;cout << "p3 的年龄为: " << p3.age << endl;// 注意事项:// 不要利用拷贝构造函数去初始化匿名对象, 编译器认为是对象声明// Person(p3);// 3. 隐式转换法Person p5 = 10; // 有参构造 相当于 Person p5 = Person(10);Person p4 = p2; // 拷贝构造
}int main(int argc, char const *argv[])
{test01();return 0;
}

2.3 拷贝构造函数调用时机

// 1. 使用一个已经存在的对象来初始化一个新对象
// 2. 值传递的方式给函数参数传值的时候
// 3. 以值方式返回一个对象
#include <iostream>
using namespace std;
#include <string>
#include "point.h"
#include "cricle.h"// 拷贝构造函数调用时机// 1. 使用一个已经存在的对象来初始化一个新对象class Person{
public:Person(){cout  << "Person 默认构造函数" << endl;}Person(int age){this->m_Age = age;cout << "Person 有参构造函数" << endl;}Person(const Person &p){cout << "Person 拷贝构造函数调用" << endl;m_Age = p.m_Age;}int m_Age;~Person(){cout << "Person 析构函数调用" << endl;}
};void test01(){Person p1(10);Person p2(p1);cout << "p2的年龄为:" << p2.m_Age << endl;
}// 2. 值传递的方式给函数参数传值的时候
void doWork(Person p){}
void test02(){Person p;doWork(p);
}// 3. 以值方式返回一个对象
Person doWork2(){cout << "doWork2 函数调用" << endl;Person p1(200);cout << " p1 " << &p1 << endl;return p1; // 启用一种优化机制叫做“返回值优化”(Return Value Optimization, RVO)。RVO 允许编译器直接在调用点创建返回的对象,从而避免了不必要的拷贝操作
}void test03(){Person p3 = doWork2();cout << "test03 函数调用 p3 " << &p3 << p3.m_Age << endl;
}int main(int argc, char const *argv[])
{test03();return 0;
}

2.4 构造函数调用规则

// 默认情况下,c++编译器至少会给一个类添加3个函数
// 1.默认构造函数(空实现)
// 2.默认析构函数(空实现)
// 3.默认拷贝构造函数,对每个非static成员变量进行值拷贝// 构造函数调用规则
// 1.如果用户定义有参构造函数,c++不在提供默认构造函数,但是会提供默认拷贝构造函数
// 2.如果用户定义拷贝构造函数,c++不会提供其他构造函数

class Person{
public:Person(int age){this->age = age;}// Person(const Person &p){//     cout << "拷贝构造函数" << endl;//     this->age = p.age;// }int age;
};int main(int argc, char const *argv[])
{Person p1(10);Person p2(p1);cout << p2.age << endl;return 0;
}

2.5 深拷贝与浅拷贝

// 深拷贝与浅拷贝
// 深拷贝:在堆区申请空间,拷贝数据
// 浅拷贝:只拷贝堆区地址,两个对象指向同一块内存
#include <iostream>
using namespace std;
#include <string>
#include "point.h"
#include "cricle.h"class Car{
public:string name;
};class Person{
public:int age;int *m_Height;Car *car;Person(){cout << "默认构造函数" << endl;}Person(int age, int height, Car *car){m_Height = new int(height);this->age = age;this->car = new Car(*car);cout << "有参构造函数" << endl;}Person(const Person &p){cout << "拷贝构造函数" << endl;this->age = p.age;this->m_Height = new int(*p.m_Height);this->car = new Car(*p.car);}~Person(){// 析构函数释放堆区数据if (m_Height != NULL){delete m_Height;m_Height = NULL;}if(car != NULL && (*car).name != ""){cout << "car 释放 " << (*car).name << " " << car << endl;delete car;car = NULL;}cout << "析构函数" << endl;}};void test01(){Car car;  // 创建对象,在栈区,不要在堆区申请内存,因为容易造成野指针car.name = "宝马";Person p1(18,170,&car);cout << "p1的年龄:" << p1.age  << "身高 " << *p1.m_Height << " " << p1.m_Height << endl;Person p2(p1);cout << "p2的年龄:" << p2.age  << "身高 " << *p2.m_Height <<  " " << p2.m_Height<< endl;p2.car->name = "su7";cout << "p1 car的名字:" << p1.car->name <<  " " << p1.car << endl;cout << "p2 car的名字:" << p2.car->name <<  " " << p2.car << endl;
}int main(int argc, char const *argv[])
{test01();return 0;
}

2.6 初始化列表

// 初始化列表
// 作用: c++提供了初始化列表语法,可以像使用=赋值一样对类成员进行初始化
// 语法: 类名(参数类型 参数名) : 成员变量名1(参数名), 成员变量名2(参数名), 成员变量名3(参数名){}
#include <iostream>
using namespace std;
#include <string>
#include "point.h"
#include "cricle.h"class Person{
public:// 传统方式// Person(int a, int b, int c){//     m_A = a;//     m_B = b;//     m_C = c;// }// 初始化列表方式Person() : m_A(10), m_C(20), m_B(30){}// 初始化列表可以有默认值Person(int a, int b, int c) : m_A(a), m_B(b), m_C(c){}int m_A;int m_B;int m_C;
};int main(int argc, char const *argv[])
{Person p(30, 20, 10);cout << "p.m_A = " << p.m_A << endl;cout << "p.m_B = " << p.m_B << endl;cout << "p.m_C = " << p.m_C << endl;return 0;
}

2.7 类对象作为类成员

#include <iostream>
using namespace std;
#include <string>
#include "point.h"
#include "cricle.h"// 类对象作为类成员表
class Phone{
public:Phone(string brand){this->brand = brand;cout << "Phone构造函数" << endl;};string brand;~Phone(){cout << "Phone析构函数" << endl;}
};class Person{
public:// Phone phone = brand; 隐试调用Phone的构造函数Person(string name, string brand):name(name), phone(brand){cout << "Person构造函数" << endl;};string name;Phone phone;~Person(){cout << "Person析构函数" << endl;}};// 其他对象作为类成员表,先构造其他对象,再构造类对象,析构时先析构类对象,再析构其他对象void test01(){// string brand = "小米";// Phone p = brand;// cout << p.brand << endl;Person p1("张三", "苹果");cout << p1.name << "的手机品牌是:" << p1.phone.brand << endl;
}int main(int argc, char const *argv[])
{test01();return 0;
}

2.8 静态成员

静态成员就是在成员变量和成员函数上加上关键字static,称为静态成员。静态成员变量
1. 静态成员变量在所有对象中只有一个副本,当修改其中一个对象的值时,其他对象的值也会发生变化。
2. 在编译阶段分配内存,在程序运行期间不变。
3. 类内声明,类外初始化静态成员函数
4. 所有对象共享一个函数
5. 静态成员函数只能访问静态成员变量
#include <iostream>
using namespace std;
#include <string>
#include "point.h"
#include "cricle.h"//  静态成员变量
class Person{
public:static int m_A;int m_C;static void func(){m_A = 100;// m_C = 100; // 静态成员函数中不能访问非静态成员变量cout << "func调用" << endl;func2();};private:static int m_B;   static void func2(){cout << "func2调用" << endl;};
};int Person::m_A = 10;
int Person::m_B = 10;
void test01(){Person p1;Person p2;// 通过对象访问静态成员p2.m_A = 200;cout << p1.m_A << endl;p2.func();// 通过类名访问静态成员cout << Person::m_A << endl; Person::func();// Person::func2(); // 私有静态成员函数不能在类外访问
}int main(int argc, char const *argv[])
{test01();return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com