首页 > 编程语言 >C++中的类

C++中的类

时间:2024-07-08 22:44:17浏览次数:16  
标签:name int 成员 C++ stu year void

class

认识class

 //一个简单的类的创建
 #include<iostream>
 using namespace std;
 
 class stu{
 public:
 	string name;
 	int year;
 	void set_value(string name,int year);
 	void show(){
 		cout << '姓名:'<< name << '年龄:'<< year << endl;
 	}
 };
 void stu::set_value(string name,int year){
 	name = name1;
 	year = year1;
 }
 
 int main(){
 	stu student;
 	student.set_value('鹤清',20);
 	student.show();
 }

类的访问权限

  • 在类的内部,无论成员被申明为public还是private,都可以访问
  • 在类的外部,只能访问public成员,不能访问private和protected成员
  • 成员函数算类的内部的部分
  • 如果不设置权限,则默认全部内容都为private

简单使用类

  • 类的成员函数可以直接访问该类其他成员函数(可递归)

     #include<iostream>
     using namespace std;
     
     class stu{
     public:
     	string name;
     	int year;
     	int times = 0;
     	void set_value(string name,int year);
     	void show(){
     		if(times++ > 10) return; //终止递归条件:运行10次
     		cout << '姓名:'<< name << '年龄:'<< year << endl;
     	}
     };
     
     int main(){
     	stu student;
     	student.set_value('鹤清',20);
     	student.show();
     }
    
  • 类的成员函数可以重载,可以使用默认参数

  • 类的指针的用法与结构体指针用法相同

  • 类的成员可以是任意数据类型(类中枚举)

     class stu{
     public:
     	string name;
     	int year;
     	enum{girl=1,boy=2};
     	void set_value(string name,int year);
     	void show(){
     		cout << '姓名:'<< name << '年龄:'<< year << endl;
     		if(sex==girl){;}
     	}
     };
    
  • 类可以创建对象数组,就像结构体数组一样

  • 对象可以作为实参传递给函数,一般传引用

  • 在类的外部,一般不直接访问(读和写)对象的成员,而是用成员函数

    class stu{
     public:
     	string name;
     	int year;
     	int get_age(){
     		return age;
     	}
     	void set_age(int age1){
     		age = age1;
     	}
     	void set_value(string name,int year);
     	void show(){
     		cout << '姓名:'<< name << '年龄:'<< year << endl;
     	}
     };
     int main(){
     	stu student;
     	student.set_value('鹤清',20);
     	//student.age = 21 #一般不这么用
    
  • 对象一般不用memset()清空成员变量,可以写一个专用于清空成员变量的成员函数

     class stu{
     public:
     	string name;
     	int year;
     	int times = 0;
     	void initdata(){ //清空全部的成员变量
     		name.clear();
     		age = 0;
     	}
     	void set_value(string name,int year);
     	void show(){
     		if(times++ > 10) return; //终止递归条件:运行10次
     		cout << '姓名:'<< name << '年龄:'<< year << endl;
     	}
     };
    
  • 对类和对象用sizeof运算意义不大,一般不用

  • 用结构体描述纯粹的数据,用类描述对象

  • 在类的声明中定义的函数都将自动成为内联函数;在类的声明之外定义的函数如果使用了inline限定符,也是内联函数

     class stu{
     public:
     	string name;
     	int year;
     	void set_value(string name,int year);
     	void show(){
     		cout << '姓名:'<< name << '年龄:'<< year << endl;
     	}
     };
     inline void stu::set_value(string name,int year){
     	name = name1;
     	year = year1;
     }
    
  • 为了区分类的成员变量和成员函数的形参,把成员变量名加m_前缀或_后缀,如m_name或name_

  • 类的分文件编写。一般情况下,把声明类的代码放在头文件中,把成员函数定义的代码放在源文件中

构造函数和析构函数(自动执行)

  • 构造函数:在创建对象时,自动的进行初始化工作
  • 析构函数:在销毁对象前,自动的完成清理工作

构造函数

  • 访问权限必须是public

  • 函数名必须与类名相同

  • 没有返回值,也不写void

  • 可以有参数,可以重载,可以有默认参数

  • 创建对象时会自动调用一次,不能手工调用

     class stu{
     public:
     	string m_name;
     	int m_year;
     	char m_memo[301]; //备注
     	
     	stu(){            //构造函数
     		m_name.clear();
     		m_age = 0;
     		memset(m_memo,0,sizeof(m_memo));
     	}
     	void set_value(string name,int year);
     	void show(){
     		cout << '姓名:'<< name << '年龄:'<< year << endl;
     	}
     };
     
     int main(){
     	stu student;
     	//student.set_value('鹤清',20);
     	student.show();
     }
    
  • 创建对象的时候不要在对象名后面加空的圆括号,编译器误认为是声明函数

  • 在构造函数名后面加括号和参数不是调用构造函数,是创建匿名对象

     class stu{
     public:
     	string m_name;
     	int m_year;
     	char m_memo[301]; //备注
     	
     	stu(){            //构造函数
     		m_name.clear();
     		m_age = 0;
     		memset(m_memo,0,sizeof(m_memo));
     	}
     	 stu(string name){            //构造函数
     		//m_name.clear();
     		//m_age = 0;
     		//memset(m_memo,0,sizeof(m_memo));
     		stu(); //代替上面的三行代码,其实会遗留bug,真正意义不是调用构造函数,而是创建一个匿名对象,也叫临时对象。如果类里面有指针,就会很危险
     		m_name = name;
     	}
     	
     	
     	void set_value(string name,int year);
     	void show(){
     		cout << '姓名:'<< name << '年龄:'<< year << endl;
     	}
     };
    

析构函数

  • 访问权限必须是public

  • 函数名必须在类名前加~

  • 没有返回值,也不写void

  • 没有参数,不能重载

  • 销毁对象前只会自动调用一次,但是可以手工调用(手工调用应用场景很少)

     class stu{
     public:
     	string m_name;
     	int m_year;
     	char m_memo[301]; //备注
     	
     	stu(){            //构造函数
     		m_name.clear();
     		m_age = 0;
     		memset(m_memo,0,sizeof(m_memo));
     	}
     	~stu(){
     		cout << "调用了析构函数\n";
     	}
     	
     	void set_value(string name,int year);
     	void show(){
     		cout << '姓名:'<< name << '年龄:'<< year << endl;
     	}
     };
     
     int main(){
     	stu student;
     	//student.set_value('鹤清',20);
     	student.show();
     }
    

拷贝构造函数

 class stu{
 public:
 	string m_name;
 	int m_year;
 	char m_memo[301]; //备注
 	
 	stu(){            //构造函数
 		m_name.clear();
 		m_age = 0;
 		memset(m_memo,0,sizeof(m_memo));
 	}
 	void set_value(string name,int year);
 	void show(){
 		cout << '姓名:'<< name << '年龄:'<< year << endl;
 	}
 };
 
int main(){
 	stu student1;
	student1.m_name='鹤清';student1.m_year=21;
	//两种方式
	stu student2(student1);
	stu student3=student1;
 }
  • 语法: 类名(const 类名&对象名)

  • 访问权限必须是public

  • 函数名必须与类名相同

  • 没有返回值,不写void

  • 如果类中定义了拷贝构造函数,编译器将不提供拷贝构造函数

     class stu{
     public:
     	string m_name;
     	int m_year;
     	char m_memo[301]; //备注
     	
     	stu(){            //构造函数
     		m_name.clear();
     		m_age = 0;
     		memset(m_memo,0,sizeof(m_memo));
     	}
     	stu(const stu&gg){//拷贝构造函数
     		m_name = "漂亮的"+gg.m_name;
     		m_age = gg.m_age - 1;
     	}
     	
     	void set_value(string name,int year);
     	void show(){
     		cout << '姓名:'<< name << '年龄:'<< year << endl;
     	}
     };
     int main(){
     	stu student1;
    	student1.m_name='鹤清';student1.m_year=21;
    	//两种方式
    	stu student2(student1);
    	stu student3=student1;
     }
    

初始化列表

class stu{
public:
	string m_name;
	int m_year;
	char m_memo[301]; //备注
	
	stu():m_name("鹤清"),m_year(21)
	{            //构造函数
		;
	}
	
	void show(){
		cout << "姓名:"<< m_name << "年龄:"<< m_year << endl;
	}
};

int main(){
	stu student1;
	student1.show();
}
  • 如果成员已经在初始化列表中,则不应该在构造函数中再次赋值
  • 初始化列表的括号中可以是具体的值,也可以是构造函数的形参名,还可以是表达式
  • 初始化列表与赋值有本质的区别,如果成员是类,使用初始化列表调用的是拷贝构造函数,而赋值则是先创建对象(调用普通构造函数),然后再赋值
  • 如果成员是类,初始化列表对性能略有提升
  • 如果成员是常量和引用,必须使用初始列表,因为常量和引用只能在定义的时候初始化
  • 如果成员是没有默认构造函数的类,则必须使用初始列表

const修饰成员函数

在类的成员函数后面加const关键字,表示在成员函数中保证不会修改调用对象的成员变量

实际开发中,如果成员函数不会修改成员变量,就应该加const修饰(编程规范)

  • mutable可以突破const的限制,被mutable修饰的成员变量,将永远处于可变的状态
  • 非const成员函数可以调用const成员函数和非const成员函数
  • const成员函数不能调用非const成员函数
  • 非const对象可以调用const修饰的成员函数和非const修饰的成员函数
  • const对象只能调用const修饰的成员函数,不能调用非const修饰的成员函数

this 指针

 class stu{
 public:
 	string m_name;
 	int m_year;
 	char m_memo[301]; //备注
 	
 	stu(){            //构造函数
 		m_name.clear();
 		m_age = 0;
 		memset(m_memo,0,sizeof(m_memo));
 	}
 	void set_value(string name,int year);
 	
 	const stu& pk(const stu& g){
 		if (g.m_year<m_year) return g;
 		return *this;
 	}
 	
 	void show(){
 		cout << '姓名:'<< name << '年龄:'<< year << endl;
 	}
 };
 
 int main(){
 	stu s1("张三",1),s2("李四",2),s3("王五",3);
 	const stu& s4 = s1.pk(s2).pk(s3);
 	s4.show();
 }

静态成员

类的静态成员包括静态成员变量和静态成员函数

用静态成员可以变量实现多个对象之间的数据共享,比全局变量更有安全性

用static关键字把类的成员变量声明为静态,表示它在程序中是共享的

静态成员变量不会在创建对象的时候初始化,必须在程序的全局区用代码清晰的初始化(用范围解析运算符::)

静态成员使用类名加范围解析运算符::就可以访问,不需要创建类对象

class stu{
 public:
 	string m_name;
 	static int m_year; //静态变量
 	stu(const string& name,int year){
 		m_name = name;
 		m_year = year;
 	}
 	void show(){
 		cout << '姓名:'<< name << '年龄:'<< year << endl;
 	}
 };

 int stu::m_year = 8;  //不能放在类中和main函数中,不创建对象也可以访问
 
 int main(){
 	stu student;
 	student.set_value('鹤清',20);
 	student.show();
 }
  • 如果类的成员声明为静态的,就可以把它与类的对象独立开来
  • 静态成员函数只能访问静态成员,不能访问非静态成员
  • 静态成员函数中没有this指针
  • 非静态成员函数可以访问静态成员
  • 私有静态成员变量在类外无法访问
  • const静态成员变量可以在定义类的时候初始化

继承

#include <iostream>
using namespace std;
// 基类 Shape
class Shape 
{
   public:
      void setWidth(int w)
      {
         width = w;
      }
      void setHeight(int h)
      {
         height = h;
      }
   protected:
      int width;
      int height;
};
// 基类 PaintCost
class PaintCost 
{
   public:
      int getCost(int area)
      {
         return area * 70;
      }
};
// 派生类
class Rectangle: public Shape, public PaintCost
{
   public:
      int getArea()
      { 
         return (width * height); 
      }
};
 
int main(void)
{
   Rectangle Rect;
   int area;
   Rect.setWidth(5);
   Rect.setHeight(7);
   area = Rect.getArea();
   // 输出对象的面积
   cout << "Total area: " << Rect.getArea() << endl;
   // 输出总花费
   cout << "Total paint cost: $" << Rect.getCost(area) << endl;
   return 0;
}

友元

如果要访问类的私有成员变量,调用类的公有成员函数是唯一的办法,而类的私有成员函数则无法访问。友元提供了另一访问类的私有成员的方案,友元有三种:

  1. 友元全局函数:在友元全局函数中,可以访问另一个类的所有成员

    class stu{
    friend void show_address();  //声明为友元
     private:
     	string m_address;
     public:
     	string m_name;
     	static int m_year; //静态变量
     	stu(const string& name,int year){
     		m_name = name;
     		m_year = year;
     	}
     	void show(){
     		cout << '姓名:'<< name << '年龄:'<< year << endl;
     	}
     };
     
    void show_address{
    	stu ss;
    	cout << ss.m_address<< endl;
    }
    
     int main(){
     	stu student;
     	student.set_value('鹤清',20);
     	student.show();
     }
    
  2. 友元类:在友元类所有成员函数中,都可以访问另一个类的所有成员

    • 友元关系不能被继承

    • 友元关系是单向的,不具备交换性

      若类B是类A的友元,类A不一定是类B的友元。类B是类A的友元,类C是类B的友元,类C不一定是类A的友元

  3. 友元成员函数:在友元类某成员函数中,可以访问另一个类的所有成员

标签:name,int,成员,C++,stu,year,void
From: https://www.cnblogs.com/qzt2cool/p/18290815

相关文章

  • 【C++深度探索】继承机制详解(二)
    hellohello~,这里是大耳朵土土垚~......
  • 深入理解C++线程池的实现
    深入理解C++线程池的实现在多线程编程中,线程池是一种重要的工具,用于管理和执行多个任务,有效地利用系统资源和提升程序性能。一、线程池的了解1.理解线程池的基本概念与作用线程池由任务队列和一组工作线程组成,任务队列用于存储待执行的任务,工作线程则负责从队列中取出......
  • C++ 项目目录结构
    project_root/├──src/#源代码目录│├──main.cpp#主函数文件│├──MyClass.cpp#类的实现文件│└──...#其他源文件│├──include/#头文件目录│├──MyClass.h#类的头......
  • 将C++ DLL文件输出设置到项目调试目录
    将C++DLL文件输出设置到项目调试目录在项目开发过程中,有时需要边开发DLL代码,边开发项目,将DLL文件输出设置到解决方案的项目调试目录,调试过程中可一键生成解决方案,省去重新更换DLL文件的过程。前提:在同一解决方案下添加项目工程与DLL工程。前文提示:关于C++DLL的封装可参......
  • C++基础入门语法--代码基础框架
    文章内容概括:了解学习导入头文件、使用usingnamespacestd简化代码、创建程序基础框架、学习使用return(如需要直接复制请到文章最末尾)正文:1.学习导入头文件:    在Dev-C++编辑器中新建文件,在文件的第一行中输入:#include<iostream>    以上代码为C++导入......
  • c++ primer plus 第15章友,异常和其他:异常,15.3.5 异常规范和 C++11
    c++primerplus第15章友,异常和其他:异常,15.3.5异常规范和C++1115.3.5异常规范和C++11文章目录c++primerplus第15章友,异常和其他:异常,15.3.5异常规范和C++1115.3.5异常规范和C++1115.3.5异常规范和C++11有时候,一种理念看似有前途,但实际的使用效果并......
  • c++ primer plus 第15章友,异常和其他:15.3.1 调用abort()02
    c++primerplus第15章友,异常和其他:15.3.1调用abort()02调用abort()02文章目录c++primerplus第15章友,异常和其他:15.3.1调用abort()0215.3.1调用abort()15.3.1调用abort()对于这种问题,处理方式之一是,如果其中一个参数是另一个参数的负值,则调用abort(......
  • c++ primer plus 第15章友,异常和其他:异常,15.3.3 异常机制
    #c++primerplus第15章友,异常和其他:异常,15.3.3异常机制异常,15.3.3异常机制文章目录15.3.3异常机制15.3.3异常机制程序清单15.9error3.cpp程序清单15.10excmean.h程序清单15.11error4.cpp15.3.3异常机制15.3.3异常机制下面介绍如何使用异常机制来处......
  • 自动驾驶感知项目-基于多线激光雷达的小目标锥桶空间位置检测算法(ROS,C++,滤波)
    一:序言想了解更多自动驾驶项目课程以及获取学习代码的可以参考这个链接无人车采用纯跟踪算法跟随离线路径感知锥桶项目中:滤波处理是进行激光雷达目标检测的常见步骤,对原始点云数据进行预处理达到减少噪声、无效点或者数据量的效果。常用的点云滤波方法包括体素滤波、法......
  • C++数据结构底层实现算法
    1.vector底层数据结构为数组,支持快速随机访问2.list底层数据结构为双向链表,支持快速增删3.deque底层数据结构为一个中央控制器和多个缓冲区,详细见STL源码剖析P146,支持首尾(中间不能)快速增删,也支持随机访问deque是一个双端队列(double-endedqueue),也是在堆中保存内容的.每个......