▲什么是类?类有什么作用?

 

目录

一.什么是类?

二.类与对象是什么关系?

三.类和结构体有什么区别呢?

四.如何创建一个类?

五.如何创建一个类的对象?

1.对象的创建

2.创建对象的初始化

1)默认构造函数

2)普通构造函数

3)复制构造函数

4)复制构造函数

5)移动构造函数

*右值与左值的区别

*如果觉得以上知识点比较抽象,建议结合这里展示的以现实生活中的钟表为对象创建的类来辅助理解

 六.什么是组合类?

1.那么组合类有什么值得注意的地方呢?

1)对组合类中类成员的初始化

 *如果觉得以上知识点比较抽象,建议结合这里展示的以现实生活中的线为对象(两个点为成员类)创建的类来辅助理解

2)​什么是前向引用声明?

*前向引用声明注意事项


什么是类?

类的定义
类是将同类对象的共同属性和行为抽象出来形成的一个相对复杂的数据类型, 这与结构体一样,都是为了描述一个相对复杂的对象。

类与对象是什么关系?

类与对象的关系
*类相当于设计出来的图纸,对象相当于产品
1.对象是现实中的对象在程序中的模拟。
2.类是同一类对象的抽象,对象是类的某一特定实体。
3.定义类的对象,才可以通过对象使用类中定义的功能。

类和结构体有什么区别呢?

类与结构体的区别
类是C++中对于C语言中的结构体的延伸
1.类相比与结构体,它可以将函数作为成员,一般在类中声明,把函数体放在类外实现(若将函数体放在类中要将inline关键字放在前面)
2.结构体和类都可以被访问(对象名.成员名/对象指针->成员名), 但区别是类中可以使用三个访问说明符(用来设定访问权限)

访问说明符:
public:类内,类外都可以访问。(公开)//类内指的是定义成员所在的代码块中;类外指的是类内以外的区域
protected:类内、派生类或者友元的成员访问,但类外不能访问。(只要与该类相关的区域都可以访问)
private(默认):不能被从类外或者派生类中访问。(对于类外,只有友元才可以访问)
友元和派生类:
友元(friend):friend 关键字修饰的某个函数或者类,可以使得在被修饰者在不成为成员函数或者成员类的情况下,访问该类的私有(private)或者受保护(protected)成员。
派生类(derived class):C++ 允许使用一个类作为基类,并通过基类派生出派生类,用来继承基类中的成员变量和成员函数。可以提高代码的复用率。

如何创建一个类?

创建类的作用
创建类实质上就是将抽象出的数据,代码封装在一起(类声明中的{}),形成类。
*目的:增强安全性和简化编程,使用者不必了解具体细节,而只需要通过外部接口,以特定的访问权限,来使用类的成员。
语法形式
class 类名称
{
    public:
           公有成员(类与外部的接口)
    protected:
              保护型成员(类的继承)
    privat:
           私有成员(辅助作用的数据或函数)
}

如何创建一个类的对象?

对象的创建
类名 对象名;
例如:Clock myClock;

创建对象的初始化
由于类是复杂的数据类型,不能简单地进行赋值操作来进行对象的初始化,C++语法提供了特殊的机制-构造函数(对象被创建时会被自动调用)


默认构造函数(初始值为空)
1.如果没定义构造函数,会自动生成程序内定的默认构造函数;否则,不生成。
2.指示编译器创建默认构造函数:类名()=default(按照需要生成)


普通构造函数
利用函数的传参功能,对私有成员赋值
构造函数与普通函数有什么区别
1.不需要返回值,也不加void,和成员函数一样,需要加作用域限定符"类名::"
2.
1)可以用初始化列表的形式进行初始化
2)也可以以委托构造函数的形式,将只是参数表不同,初始化算法相同的构造函数进行初始化


复制构造函数
对类的对象进行赋值,将类的对象作为参数进行传参等操作时,编译器不能直接获得类中数据,而是采用引用(这里为左值)的方式进行引用目标类,然后直接使用引用出来的目标类赋值给其他类的各个成员,以达赋值效果

左值引用
对持久存在变量的引用称为左值引用,用&表示

复制构造函数被调用的三种情况
1.定义一个对象时,以本类另一个对象作为初始值,发生复制构造;(直接赋值)
2.如果函数的形参是类的对象,调用函数时,将使用实参对象初始化形参对象,发生复制构造;(传参)
3.如果函数的返回值是类的对象,函数执行完成返回主调函数时,将使用return语句中的对象初始化一个临时无名对象,传递给主调函数,此时发生复制构造。(以返回值的形式赋值)
移动运算符


移动构造函数
基于右值引用,移动构造函数通过移动数据方式构造新对象,与复制构造函数类似,移动构造函数参数为该类对象的右值引用。示例如下

右值引用
对持久存在变量的引用称为左值引用,用&表示(即第3章引用类型)·对短暂存在可被移动的右值的引用称之为右值引用,用&&表示。
#include<utility>
class astring
public:
std::string s;
astring (astring&& o) noexcept:s(std:move(o.s))
移动构造函数不分配新内存,理论上不会报错,为配合异常捕获机制,需声明noexcept表明不会抛出异常(将于12章异常处理介绍)
被移动的对象不应再使用,需要销毁或重新赋值

右值与左值的区别
简单理解:左值是位于赋值运算左侧的对象或变量,右值是位于赋
值运算右侧的值。

float n = 6;
o float &lr n= n;//左值引用
ofloat &&rr_n=n;//错误,右值引用不能绑定到左值
o float &&rr n = n* nj//右值表达式绑定到右值引用
通过标准库<utility>中的move函数可将左值对象移动为右值。float n = 10;
o float &&rr n = std:move(n);//将n转化为右值
使用move函数承诺除对n重新赋值或销毁外,不以rr_n以外方式使用

如何实现对类的使用
在类中对成员的访问:直接使用成员名访问。
在类外对成员的访问:使用"对象名.成员名"方式访问public属性的成员。

如果觉得以上知识点比较抽象,建议结合这里展示的以现实生活中的钟表为对象创建的类来辅助理解

#define  _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
class Clock{
public:
	Clock(int newH, int newM, int newS);
	Clock() = default; //指示编译器依据是否有初始化来判断是否创建默认构造函数
	Clock(Clock&C);//复制构造函数
	//Clock(Clock &C) = delete;//指示编译器不生成默认复制构造函数
	//Clock(Clock&&C)noexcept:hour(move(C.hour)), minute(move(C.minute)), second(move(C.second)){}
	//移动构造函数,被移动的对象不应再使用,需要销毁或重新赋值
	~Clock();//析构函数
	void setTime();//函数原型的声明
	void showTime();
    int gethour(){ return hour; };
	int getminute(){ return minute; };
private:
	int hour, minute, second;//私有数据成员
};
Clock::Clock(int newH, int newM, int newS) :hour(newH), minute(newM), second(newS){}
Clock::Clock(Clock&C) : hour(C.hour), minute(C.minute), second(C.second){}
Clock::~Clock(){}
void Clock::setTime(){//成员函数的定义,与普通全局函数定义多了”Clock::“作用域限定符
	cin >> hour >> minute >> second;//成员函数可直接操作私有成员(属于类内访问)
}
void Clock::showTime(){//把函数体放在类外实现(若将函数体放在类中要将inline关键字放在前面)
	printf("%02d:%02d:%02dn", hour, minute, second);
}
void get(Clock C){
	cout << C.gethour() <<":"<< C.getminute() << endl;
}
Clock fuzhi(Clock C){ return C; }
int main()
{
	Clock myClock(0,0,0);//创建对象
	cout << "Frist time set:" << endl;
	myClock.setTime();//类外访问成员函数
	cout << "Frist time output:" << endl;
	myClock.showTime();
	Clock lastClock(myClock);//用myClock初始化yourClock
	cout << "second time set" << endl;
	myClock.setTime();
	cout << "Last time output:" << endl;
	lastClock.showTime();
	cout << "second time output:" << endl;
	myClock.showTime();
	cout << "hour and minute of second time output:" << endl;
	get(myClock);//对象myClock作为实参,会使用复制构造函数
	lastClock = myClock;
	lastClock = fuzhi(myClock);//myClock作为返回值,会使用复制构造函数
	cout << "Last time output:" << endl;
	lastClock.showTime();
}

什么是组合类?


组合类的理解
组合类本质也是类,那为什么叫做组合类呢,因为组合类中有类作为成员。


那么组合类有什么值得注意的地方呢?
 


创建组合类对象时的成员初始化次序
成员初始化顺序:按对象成员的声明顺序,先声明者先构造。
初始化列表中未出现的成员对象,调用用默认构造函数(即无形参的)初始化.处理完初始化列表之后,再执行构造函数的函数体。
 

对组合类中类成员的初始化

组合类对于类成员的初始化相对其他成员的初始化要更加麻烦一点,因为在对组合类初始化时所需要的成员数据也是类,在进行初始化时需要对组合类的构造函数传参,成员类作为参数需要进行使用复制构造函数,然后才能对组合类进行初始化,再使用组合类的构造函数。

 如果觉得以上知识点比较抽象,建议结合这里展示的以现实生活中的线为对象(两个点为成员类)创建的类来辅助理解

#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
class Point {//Point类的定义
public:
	Point(int newX, int newY);
	Point(Point&P);
	int getX(){ return x; }
	int getY(){ return y; }
private:
	int x, y;
};
Point::Point(int newX, int newY) :x(newX), y(newY) {}
Point::Point(Point&P) : x(P.x), y(P.y){}
class Line{
public:
	Line(Point xp1, Point xp2);
	Line(Line&L);
	double getLen(){ return len; }
private:
	Point p1, p2;
	double len;
};
Line::Line(Point xp1, Point xp2) :p1(xp1), p2(xp2){
	cout << "Calling constryctor of Line" << endl;
	double x = static_cast<double>(p1.getX() - p2.getX());
	double y = static_cast<double>(p1.getY() - p2.getY());
	len = sqrt(x*x + y*y);
}
Line::Line(Line&L) :p1(L.p1), p2(L.p2),len(L.len){}
int main()
{
	Point myp1(1, 1), myp2(4, 5);//建立Point类的对象
	Line line(myp1, myp2);//建立Line类的对象
	Line line2(line);//利用复制构造函数建立一个新对象
	cout << "The length of the line is:";
	cout << line.getLen() << endl;
	cout << "The length of the line2 is:";
	cout << line2.getLen() << endl;
	return 0;
}

什么是前向引用声明?

类应该先声明,后使用
如果需要在某个类的声明之前,引用该类,则应进行前向引用声明。前向引用声明只为程序引入一个标识符,但具体声明在其他地方。

前向引用声明注意事项
使用前向引用声明虽然可以解决一些问题,但它并不是万能的。
在提供一个完整的类声明之前,不能声明该类的对象,也不能在内联成员函数中使用该类的对象。
当使用前向引用声明时,只能使用被声明的符号,而不能涉及类的任何细节。
 

例:

class B;
class A{
public:
	void f(B b);
};
class B{
public:
	void f(A a);
};

    ◆◆◆◆◆◆◆◆◆◆◆◆◆◆感谢您对这篇文章的阅读,记得一件三连哦~♡◆◆◆◆◆◆◆◆◆◆◆◆◆◆

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>