1.类
1.1类的定义
一般形式为:
class类名{
public:
<公有数据和函数>
protected:
<保护数据和函数 >
private:
<私有数据和函数>
};
1.2成员的访问属性
成员缺省定义为private的。私有成员是被隐藏的数据,只有该类的成员函数或友元函数才可以访问它
保护成员也不能通过对象访问,但是可以被该类或派生类的成员函数访问。
公有成员定义了类的外部接口。
1.3 成员函数
成员函数的实现,可以放在类体内;也可以放在类体外,但必须在类体内给出原型说明。
放在类体内定义的函数被默认为内联函数,而放在类体外定义的函数是一般函数,如果要定义为内联函数 则需在前面加上关键字inline。
在类体外定义成员函数的一般形式为:
<返回类型><类名>::<成员函数名>(<参数说明>)
{
类体
}
类是具有相同属性和方法的一类对象集合的抽象,它包含数据抽象(即数据成员)和行为抽象(即成员函数)
定义类的过程就是对问题进行抽象和封装的过程
为了减少代码的重复,加快编译速度,在大型程序设计中,C++的类结构常常被分成两部分:
一部分是类的界面,
另一部分是类的实现。
2.对象
2.1对象的声明
对象是类的实例或实体。
一般格式为:
<类名><对象名表>;
例如,声明类Point的对象:
Point p1,p2;
Point p[3];
Point *p3;
Point &rp=p1;
2.2对象成员的访问
1.圆点访问方式
对象名.成员名或(*指向对象的指针).成员名
2.指针访问方式
对象指针变量名->成员名或(&对象名)->成员名
3.构造函数与析构函数
3.1构造函数的特点
构造函数是一种特殊的成员函数,对象的创建和初始 化工作可以由它来完成,其格式如下:
<类名>::〈类名>(<形参表>)
{
<函数体>
}
1.构造函数特点:
被声明为公有
函数名与类名相同
可以重载
不能指定返回类型
不能被显式调用
2.默认构造函数
默认构造函数就是无参数的构造函数。既可以是自己定义的也可以是编译系统自动生成的
当没有为一个类定义任何构造函数的情况下,编译系统 就会自动生成一个无参数、空函数体的默认构造函数 其格式如下:
<类名>::<类名>()
{
}
3.2成员初始化表
带有成员初始化表的构造函数的一般形式如下:
类名::构造函数名([参数表])[:(成员初始化表) ]
{
//构造函数体
}
成员初始化表的一般形式为:
数据成员名1(初始值1),数据成员名2(初始值2),......
3.3 具有默认参数的构造函数
如果构造函数的参数值通常是不变的,只有在特殊情况下才需要改变它的参数值,这时可以将其定义成带默认参数的构造函数
3.4析构函数
1.析构函数有如下特点:
只能被声明为公有函数。
析构函数的名字同类名,与构造函数名的区别在于析构函 数名前加~,表明它的功能与构造函数的功能相反
析构函数没有参数,不能重载,一个类中只能定义一个析构函数。
不能指定返回类型
析构函数在释放一个对象时侯被自动调用。
3.5拷贝构造函数
1.拷贝构造函数的定义
拷贝构造函数是一种特殊的构造函数,它的作用是用 一个已经存在的对象去初始化另一个对象
其格式为:
<类名>::<类名>(const<类名>&<对象名>)
{
<函数体>
}
2.拷贝构造函数的特点
拷贝构造函数名字与类相同,不能指定返回类型
拷贝构造函数只有一个参数,该参数是该类的对象的引用。
它不能被显式调用
3.在以下3种情况下会被自动调用:
当用类的一个对象去初始化该类的另一个对象时
当函数的形参是类的对象,进行形参和实参结合时
当函数的返回值是类的对象,函数执行完成返回调用者时
3.6浅拷见和深拷贝
如果一个类中没有定义拷贝构造函数,则系统自动生成一 个默认的拷贝构造函数。
如Point类中,默认的拷贝构造函数为:
Point(const Point p)
{
x =p.x;
y= p.y;
}
所谓浅拷贝,就是用默认的拷贝构造函数实现数据成员逐一赋值。
需要自己写拷贝构造函数,实现额外的内容,这种称为深拷贝。
4.this指针
this指针是由C++编译器自动产生且较常用的一个隐含对象指针,它不能被显式声明。
this指针是一个局部变量,局部于某个对象。
this指针是一个const指针,不能修改它或给它赋值
this的用途
1.为了区分成员和非成员
2.类的方法需要返回当前对象的引用
5.向函数传递对象
1.使用对象作为函数参数
2.使用对象指针作为函数参数
3.使用对象引用作为函数参数
6.类的静态成员
静态成员是指声明为static的成员,在类的范围内所有对象共享该数据。
静态成员可说明为公有的、私有的或保护的。
若为公有的可直接访问,引用静态成员的格式为
<类名>::<静态成员>
对象名.公有静态成员
对象指针->静态成员
1.静态数据成员
2.静态成员函数
静态数据成员不属于任何对象,它在程序编译时创 建并且初始化,所以在该类的任何对象被创建前就存在
静态数据成员初始化的格式为:
<数据类型><类名>::<静态数据成员名>=<初始值>;
静态成员函数的定义是在一般函数定义前加上 static关键字。
(1)一般情况下,静态成员函数主要用来访问全局变量或同 一个类中的静态数据成员。可以用在 建立任何对象之前处理静 态数据成员。
(2)静态成员函数不访问类中的非静态成员
(3)静态成员函数中是没有this指针的。
(4)静态成员函数可以在类体内定义,也可以在类外定义 在类外定义时,不用static前缀。
7.类的友员
1友元函数
①友元函数是在类中说明的由关键字friend修饰的非成员函数。
②友元函数不是当前类的成员函数,而是独立于当前类的外部函 数,但它可以访问该类的所有对象的成员。
③在类中声明友元函数时,共原型为:friend<类型><友元函 数名>(<参数表>);此声明可以放在公有部分,也可以放在 保护部分和私有部分。
④友元函数可以定义在类内部,也可以定义在类的外部
2友元成员
1一个类的成员函数也可以作为另一个类的友元。
2这种成员函数不仅可以访问自己所在类对象中的所有成员 ,还可以访问friend声明语句所在类对象中的所有成员。 这样能使两个类相互合作、协调工作,完成某一任务
3友元类
①友元还可以是类,即一个类可以作为另一个类的友元
②当一个类作为另一个类的友元时,则该类中的所有成员函 数都是另一个类的友元成员,都可以访问另一个类的所有成员。
③友元类的声明格式为:friend类名;此语句可以放在公有部分,也可以放在私有部分或保护部分
8.对象成员
构造函数的调用顺序为:
对象成员所属类的构造函数、本类构造函数,如果对 象成员不只一个,则按各对象成员在类声明中的顺序依次调用它们的构造函数,对这些对象初始化
析构函数的调用顺序:
始终与构造函数的调用顺序正好相反,即先调用本类 的析构函数,再调用对象成员所在类的析构函数。
9.const
常对象
对于既需要共享、又需要防止改变的数据,应该声明为常量进行保护,因为常量在程序运行期间是不可改变的 这些常量需要用关键字const来定义。
常数据成员-------const修饰数据成员
常成员函数-------const修饰成员函数
常对象 -----const修饰类的对象
1.常数据成员------类的数据成员用const说明
(1)如果类中说明了常数据成员,则构造函数只能 通过初始化列表对该数据成员进行初始化 (2)其它函数都不能对常数据成员进行修改,只能访问。
2.常成员函数 成员函数用const说明
常成员函数的声明格式为:
类型 函数名(参数表) const:
(1)在常成员函数的原型声明及函数定义的首部都要使用关键字 const。
(2)常成员函数不能修改本类的数据成员,也不能调用普通的成员函数,从而保证了在常成员函数中不会修改数据成员的值。
(3)关键字const可以作为函数重载的标志
(4)访问属性为public的常成员函数可以通过该类的任何对象调用。
3.常对象 对象用const修饰
常对象的定义格式为:
const类名对象名;或类名const对象名;
(1)常对象必须进行初始化,而且不能被更新
(2)由于常对象的值(包括所有的数据成员的值)不能被改变,因此,通过常对象只能调用常成员函数,而不能调用类中的其他普通成员函数
在C++中,类是一种用户自定义的数据类型,对象是类的实例。
类定义了数据成员(用于存储数据)和成员函数(用于操作数据)。比如定义一个简单的“学生”类:
class Student {
public:
// 成员函数
void setName(std::string n) {
name = n;
}
std::string getName() {
return name;
}
private:
// 数据成员
std::string name;
};
这里 Student 类有一个私有数据成员 name ,还有两个公有成员函数 setName 和 getName 用于设置和获取名字。
对象是类的具体实体。可以这样使用上面的类创建对象:
int main() {
Student stu;
stu.setName("张三");
std::cout << stu.getName() << std::endl;
return 0;
}
在 main 函数中, stu 就是 Student 类的一个对象,通过对象调用成员函数来操作其中的数据成员。
C++类与对象的主要区别是什么?
在C++中,类是一种抽象的数据类型定义,对象是类的具体实例。
类主要用于定义数据成员(变量)和成员函数(方法),描述了对象的属性和行为。它像是一个蓝图或者模板,规定了将来创建对象时包含的数据和可以执行的操作。例如:
class Car {
public:
void setSpeed(int s) { speed = s; }
int getSpeed() { return speed; }
private:
int speed;
};
这个 Car 类定义了汽车的速度属性( speed ),还有设置速度和获取速度的操作。
对象是基于类创建出来的具体实体。以 Car 类为例:
int main() {
Car myCar;
myCar.setSpeed(60);
// myCar就是Car类的对象
return 0;
}
在 main 函数中 myCar 是 Car 类的一个对象,它根据 Car 类的定义,拥有自己的 speed 数据成员,可以调用 setSpeed 和 getSpeed 这些成员函数。
总结来说,类是抽象的定义,对象是实实在在能在程序中使用的实体,拥有类所定义的属性和行为。
如何定义一个类?
在C++中,定义一个类的基本语法如下:
class ClassName {
// 访问修饰符(如public、private、protected)
access_specifier:
// 数据成员(变量)
data_type member_variable;
// 成员函数(方法)声明
return_type member_function(parameters);
};
// 成员函数定义(可以在类外定义)
return_type ClassName::member_function(parameters) {
// 函数体内容
}
下面是一个简单的例子,定义一个名为 Rectangle 的类来表示矩形:
class Rectangle {
public:
// 成员函数声明,用于设置矩形的长和宽
void setDimensions(int length, int width);
// 成员函数声明,用于计算矩形的面积
int calculateArea();
private:
// 数据成员,用于存储矩形的长和宽
int length;
int width;
};
// 成员函数定义
void Rectangle::setDimensions(int l, int w) {
length = l;
width = w;
}
int Rectangle::calculateArea() {
return length * width;
}
在这个例子中:
- class 是定义类的关键字, Rectangle 是类名。
- 类中有 public 和 private 两种访问修饰符。 public 部分的成员函数可以在类的外部被访问和调用, private 部分的数据成员只能在类的内部被访问,这样可以隐藏内部数据实现细节,起到封装的作用。
- 声明了两个成员函数 setDimensions 和 calculateArea ,并在类外定义了它们的具体实现。定义类外的成员函数时,需要使用 类名::函数名的格式来表明这个函数属于哪个类。
类的定义可以在同一个CPP文件中吗?
类的定义可以放在同一个 .cpp 文件中。
通常有两种情况。一种是将类的完整定义(包括成员变量和成员函数的定义)都放在 .cpp 文件中。例如:
// example.cpp
class MyClass {
public:
void myFunction() {
// 函数体内容
}
private:
int myVariable;
};
不过这种方式如果类被多个其他文件使用,会导致代码复用性差,并且可能出现重复定义的问题。
另一种更合理的情况是将类的定义放在 .cpp 文件中,但是把类的声明放在头文件( .h 文件)中,其他文件包含头文件就可以使用这个类。比如:
// MyClass.h
class MyClass {
public:
void myFunction();
private:
int myVariable;
};
// MyClass.cpp
#include "MyClass.h"
void MyClass::myFunction() {
// 具体函数体
}
这样可以更好地组织代码,提高代码的可维护性和复用性。