当前位置:网站首页 > C++编程 > 正文

c++类和对象_c++对象

面向对象三大特性:封装、继承、多态

封装

封装的意义

1.将属性和行为作为一个整体,表现生活中的事物 语法:calss 类名{ 访问权限:属性 / 行为};

示例

#include<iostream> #include<string> using namespace std; const double PI = 3.14; //定义圆周率 class Circle //class代表设计一个类,类后面紧跟着的就是类名称 { public://访问权限中的公共权限 int m_r;//属性:定义圆的半径 double perimeter() //行为:获取圆的周长 { return 2 * PI * m_r; } }; int main() { //实例化,通过一个类创建一个对象的过程 //(通过圆类,创建具体圆的对象:周长) Circle c1; c1.m_r = 10;//给圆对象的属性进行赋值 cout << "c1周长为: " << c1.perimeter() << endl; return 0; } 

2.将属性和行为加以权限控制 三种访问权限: public 公共权限 类内可以访问,类外可以访问 protected 保护权限 类内可以访问,类外不可以访问 pirvate 私有权限 类内可以访问,类外不可以访问

在类内函数func中,函数可以访问公共权限的m_Name,保护权限的m_car,私有权限的m_password {632444F9-CE0C-414F-9101-4F42AB0F9A55}.png

而在类外函数main中,函数只能访问公共权限的m_Name

屏幕截图 2024-10-26 110251.png

struct和class的区别

class作为类其默认的访问权限为私有,struct作为类时其默认访问权限为公有

屏幕截图 2024-10-26 111840.png

屏幕截图 2024-10-26 111920.png

成员属性设置为私有

1.将所以成员属性设置为私有,可以自己控制读写权限

#include<iostream> #include<string> using namespace std; class Li { public: void setName(string Name)//设置名字可写 { m_Name = Name; } string getName() //设置名字可读 { return m_Name; } string getcar() //设置汽车可读 { return m_car; } void setpassword(int password) { m_password= password ;//设置密码可写 } private: string m_Name;//可读可写 string m_car="奔驰"; //可读不可写 string m_password; //可写不可读 }; int main() { Li c1; c1.setName("wang");//名字设置 cout << "名字为:" << c1.getName() << endl; //获取名字 cout << "汽车为: " << c1.getcar() << endl; //获取汽车 c1.setpassword(); //密码设置 return 0; } 

2.对于写权限我们可以自己检测数据的有效性

#include<iostream> #include<string> using namespace std; const double PI = 3.14; class Li { public: void setage(int age) { if (age<0 || age > 150)//对于写权限我们可以自己检测数据的有效性 { cout << "您输入的年龄" << age << "有误,请更正!" << endl; return; } m_age=age; } int getage() { return m_age; } private: int m_age=0; }; int main() { Li c1; c1.setage(60); cout << "年龄为:" << c1.getage() <<"岁" << endl; return 0; } 

若输出值超过150或者小于0则会显示

{54A998CD-14CA-46F7-A884-DBAA90597232}.png

对象的初始化和清理

构造函数和析构函数

构造函数进行初始化操作

语法:类名(){}

1.构造函数没有返回值也不写void

2.函数名称与类名相同

3.函数可以有参数,因此可以发生重载

4.程序在调用对象时会自动调用构造,无需手动调用,而且只会调用一次

析构函数 进行清理操作

语法:~类名(){}

1.构造函数没有返回值也不写void

2.函数名称与类名相同在名称前加~

3.函数不可以有参数,因此不可以发生重载

4.程序在对象销毁前会自动调用析构,无需手动调用,而且只会调用一次

*构造和析构都必须有如果我们不提供,编译器自动提供一个空实现的构造和析构

#include<iostream> #include<string> using namespace std; class person { public: person() { cout << "person的构造函数调用" << endl; } ~person() { cout << "person的析构函数调用" << endl; } }; void test01() { person p; } int main() { test01(); system("pause"); return 0; } 

函数的分类以及调用

#include<iostream> #include<string> using namespace std; class person { public: int age; //按参数分为:有参构造和无参构造(默认构造) person() { cout << "person的无参构造调用" << endl; } person(int a) { age = a; cout << "person的有参构造调用" << endl; } //按类型分为:拷贝构造和普通构造(有参构造和无参构造)、 person(const person &p) //相当于传入一个person到参数按照这个person拷贝一份 { age = p.age; cout << "person的拷贝构造调用" << endl; } }; void test01() { //括号法调用 person p1;/*无参构造调用 调用无参构造时不要加() 否则编译器会认为这是一个函数的声明不是在创建对象*/ person p2(10); //有参构造调用 person p3(p2); //拷贝构造调用 cout << "p2的年龄:" << p2.age << endl; cout << "p3的年龄" << p3.age << endl; //对p2进行拷贝 } int main() { test01(); return 0; } 

{5CA9486F-4E61-485D-A52F-25E85BF4872E}.png

显示法和隐式转化法调用

#include<iostream> #include<string> using namespace std; class person { public: int age; //按参数分为:有参构造和无参构造(默认构造) person() { cout << "person的无参构造调用" << endl; } person(int a) { age = a; cout << "person的有参构造调用" << endl; } //按类型分为:拷贝构造和普通构造(有参构造和无参构造)、 person(const person &p) //相当于传入一个person到参数按照这个person拷贝一份 { age = p.age; cout << "person的拷贝构造调用" << endl; } }; void test01() { //显示法调用 person p1;//无参构造调用 person p2= person(10); //有参构造调用 person p3=person (p2); //拷贝构造调用 cout << "p2的年龄:" << p2.age << endl; cout << "p3的年龄" << p3.age << endl; //隐式转化法 person p4 = 10; //相当于写了person p4= person(10) person p5 = p4; } int main() { test01(); return 0; } 

{27E1A5F6-50E3-4068-9F6A-C93960A85254}.png

拷贝构造函数调用时机

1.使用一个已经创建完毕的的对象来初始化一个新对象

#include<iostream> #include<string> using namespace std; class person { public: int age; person() { cout << "person的无参构造函数调用" << endl; } person(int a) { age = a; cout << "person的有参构造函数调用" << endl; } person(person &p) { age = p.age; cout << "person的拷贝构造函数调用" << endl; } ~person() { cout << "person的无参析构函数调用" << endl; } }; //1.使用一个已经创建完毕的的对象来初始化一个新对象 void test01() { person p1(20); person p2(p1); cout << "p2的年龄为:" << p2.age << endl; } int main() { test01(); system("pause"); return 0; } 

{C022BCB2-E6D8-4A4E-8D98-C933655A1A88}.png

2..值传递的方式给函数参数传值 #include #include using namespace std; class person { public: int age; person() { cout << "person的无参构造函数调用" << endl; } person(int a) { age = a; cout << "person的有参构造函数调用" << endl; } person(person &p) { age = p.age; cout << "person的拷贝构造函数调用" << endl; }

~person() { cout << "person的无参析构函数调用" << endl; } 

}; //2.值传递的方式给函数参数传值 void dowork(person p) {

} void test02() { person p; dowork(p); }

int main() { test02();

system("pause"); return 0; 

}

{CD409575-BFC4-472E-8B39-E4DADD2F9D9C}.png

 #include<iostream> #include<string> using namespace std; class person { public: int age; person() { cout << "person的无参构造函数调用" << endl; } person(int a) { age = a; cout << "person的有参构造函数调用" << endl; } person(person &p) { age = p.age; cout << "person的拷贝构造函数调用" << endl; } ~person() { cout << "person的无参析构函数调用" << endl; } }; //3.值方式返回局部对象 person dowork2() { person p1; return p1; } void test03() { person p = dowork2();//这里发生错误不懂问完再改 } int main() { test03(); system("pause"); return 0; } 

构造函数调用规则

默认情况下,编译器至少给一类三 个函数 1.默认构造函数(无参,函数体为空) 2.默认析构函数(无参,函数体为空) 3.默认拷贝构造函数,对属性进行值拷贝

构造函数调用规则如下: 如果用户定义有参构造函数,则编译器不再提供默认无参构造,但会提供默认拷贝构造 如果用户定义拷贝构造函数,则编译器不再提供其他构造函数

深拷贝和浅拷贝

浅拷贝:简单的赋值拷贝操作 深拷贝:在堆区重新申请空间,进行拷贝操作

浅拷贝:

 #include<iostream> #include<string> using namespace std; class Person { public: int m_age; int *m_height; Person() { cout << "Presond的默认构造函数调用" << endl; } Person(int age,int height) { m_age = age; m_height = new int(height);//用指针去接受堆区的数据 cout << "Presond的有参构造函数调用" << endl; } ~Person() { //析构代码将堆区开辟数据做释放操作 if (m_height != NULL /*(空的意思)*/) { delete m_height; m_height = NULL;//释放后防止野指针的出现将其置空 } cout << "Presond的析构函数调用" << endl; } }; void test01() { Person p1(18,180); cout << "p1 age:" << p1.m_age<<"p1 height"<<p1.m_height << endl; Person p2(p1); cout << "p2 age:" << p2.m_age << "p2 height" << p2.m_height << endl;//我们没有提供拷贝构造函数,编译器做了浅拷贝的操作给我们提供了一个拷贝构造函数 } int main() { test01(); system("pause"); return 0; } 

运行截图:

屏幕截图 2024-10-29 171258.png

浅拷贝问题:堆区内存重复释放

{4F111D03-5FF6-4A1B-9BED-9B8064462CB6}.png

解决办法利用深拷贝开辟一块新的内存区域

{90455041-1A4B-4557-BC31-D23AEDAD48C6}.png

#include<iostream> #include<string> using namespace std; class Person { public: int m_age; int* m_height; Person() { m_height = nullptr; cout << "Presond的默认构造函数调用" << endl; } Person(int age, int height) { m_age = age; m_height = new int(height);//用指针去接受堆区的数据 cout << "Presond的有参构造函数调用" << endl; } Person(const Person& p) { m_age = p.m_age; //m_height = p.m_height;编译器默认实现的就是这行代码 //进行深拷贝操作 m_height = new int(*p.m_height); } ~Person() { //析构代码将堆区开辟数据做释放操作 if (m_height != nullptr /*(空的意思)*/) { delete m_height; m_height = nullptr;//释放后防止野指针的出现将其置空 } cout << "Presond的析构函数调用" << endl; } }; void test01() { Person p1(18, 180); cout << "p1 age:" << p1.m_age << "p1 height:" << *p1.m_height << endl; Person p2(p1); cout << "p2 age:" << p2.m_age << "p2 height:" << *p2.m_height << endl; } int main() { test01(); system("pause"); return 0; } 

{8DDB0A26-D225-4F1A-BB03-616F6154578D}.png

初始化列表

作用:c++提供初始化列表语法,用于初始化属性

语法:构造函数():属性1(值1),属性1(值1),...{}

 #include<iostream> #include<string> using namespace std; class preson { public: preson(int a, int b, int c) :m_A(a), m_B(b),m_C(c){} void printperson() { cout << "a=" << m_A << endl; cout << "b=" << m_B << endl; cout << "c=" << m_C << endl; } private: int m_A; int m_B; int m_C; }; int main() { preson p (20,30,40); p.printperson(); system("pause"); return 0; } 

{2FB6B96B-01D9-4766-8CEC-248818C07C92}.png

类对象作为类成员

 #include<string> using namespace std; //类对象作为类成员 class phone { public: phone(string PName) { m_PName = PName; } string m_PName; //手机品牌名称 }; class person { public: //phone m_PName = PName;(隐式转换法) 编译器自动利用PName给m_PName进行构造调用 person(string Name, string PName) :m_Name(Name), m_PName(PName) { } string m_Name; phone m_PName; }; void test() { person p("张三", "华为"); cout << p.m_Name << "拿着" << p.m_PName.m_PName<<"手机" << endl; } int main() { test(); system("pause"); return 0; } 

{6A8EFA2D-12AB-4D2C-B7F5-2CE18EBE8810}.png

到此这篇c++类和对象_c++对象的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • c++练手_c++编程100例2024-11-09 16:18:04
  • c全排列数组_C++排列组合2024-11-09 16:18:04
  • ai怎么编程_c++编辑器下载2024-11-09 16:18:04
  • c++格式化输出字符串_C++格式化输出2024-11-09 16:18:04
  • 泛型程序设计与c++标准模板库_c++模板特化2024-11-09 16:18:04
  • c++编程入门教程视频_c++编程软件哪个好2024-11-09 16:18:04
  • C++学习笔记(二、C++基本概念)2024-11-09 16:18:04
  • linux c++网络编程_系统软件linux2024-11-09 16:18:04
  • cpp 泛型_泛型数组2024-11-09 16:18:04
  • c++格式化读取_cout输出科学计数法2024-11-09 16:18:04
  • 全屏图片