持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天
前言:C++支持面向对象的程序设计,类是C++的核心特征。关于面向对象的程序设计语言之前只接触过Java,而且学的也及其浅薄,只知道大概的概念。所以在学习C++的时候,感觉语法上和C语言基本差不多,不知道为什么在C语言之外再推出一个C++出来,直到后来才了解到C语言是面向过程的程序设计语言,而C++则是面向对象的。
C++类与对象
类的定义
- 类的定义是以class关键字开头,后跟类的名称
- 关键字public确定类成员的访问属性,public表示在类的外部也可以访问,也可以指定private或protected
#include<iostream>
using namespace std;
int main (){
class box{
public://
double length;
double breadth;
double height;
};
}
对象的定义
类提供的对象的蓝图,所以对象是根据类来创建的,定义类的对象 就像 定义基本类型的变量一样
box a;
box b;
访问数据成员
- 类中的数据和方法称为类的成员
- 对于类的对象的公共数据成员可以用直接成员访问运算符 . 访问
- 实例:
#include<iostream>
using namespace std;
class box{
public:
double length;
double breadth;
double height;
double get (void);
void set (double len,double bre,double hei);
};
double box::get(void){
return length * breadth * height;
}
void box::set(double len,double bre,double hei) {
length = len;
breadth = bre;
height = hei;
}
int main (){
box box1;
box box2;
box box3;
double v = 0.0 ;//体积
box1.breadth=3.0;
box1.height=2.0;
box1.length=4.0;
box1.get();
cout << "box3的体积是" << v <<endl;
box2.length=4.0;
box2.height=2.9;
box2.breadth=8.9;
box2.get();
cout << "box2的体积是" << v <<endl;
box3.set(3.0,5.0,9.0);//因为set函数也是类的成员,所以也用.来引用
v=box3.get();
cout << "box3的体积是" << v <<endl;
}
类成员函数
在上面的例子中,set函数和get函数都是类成员函数,这里再详细介绍一下:类成员函数是把定义和原型写在类定义内部的函数,就像类中定义其他变量一样,它可以操作任意类的对象,可以访问对象中的所有成员。
class box{
public:
double length;
double breadth;
double height;
double get (void){
return length * breadth * height;
}
};
成员函数可以定义在类的内部,也可以使用范围解析符 :: 来定义.
注意:在 ::运算符之前必须使用类名,
class box {
public :
double get (void);
};
double box::get (void){
return length * breadth * height;
}
创建一个对象,对象调用成员函数
box box1;
box1.get();
类访问修饰符
数据封装是面向对象编程的重要特点,它防止函数直接访问类内部成员。通过在类中标记访问修饰符 public、protected、private来指定类成员的访问限制。(默认是私有)
class box{
public:
//公有成员
protected:
//受保护的成员
private:
//私有成员
};
-
public:公有成员,在类的外部是可访问的
-
private:私有成员,在类的外部是不可访问的,只有类和友元函数可以访问私有成员
- 实际操作中,一般在私有定义数据,公有定义函数,方便在类的外部也可以调用这些函数
#include<iostream>
using namespace std;
class box{
public:
double length;
void setwidth(double);
double getwidth(void);
private:
double width;
};
void box::setwidth(double wid) {
width=wid;
}
double box::getwidth() {
return width;
}
int main (){
box box1;
//设置长度,因为length是公有的,直接访问即可
box1.length= 2.0;
cout << box1.length <<endl;
//设置宽度,因为width是私有的,所以要借助内部公有的成员函数设置
box1.setwidth(10.0);
box1.getwidth();
cout << box1.getwidth() <<endl;
return 0;
}
- protected:被保护的成员,和私有成员相似,不同点是被保护的成员在其子类中可以访问。
- 继承中的特点:有public,protected,private三种继承特点,相应的改变了基类的访问属性
类的构造函数&析构函数
构造函数
- 是类的一种特殊的成员函数,在每次类创建新对象时执行
- 构造函数的名称和类名相同,不会返回任何类型,也不会返回void
- 构造函数可用于某些成员变量设置初值
#include<iostream>
using namespace std;
class Line{
public:
void setlength(double);
double getlength(void);
Line();//构造函数
private:
double length;
};
void Line::setlength(double len) {
length=len;
}
double Line::getlength() {
return length;
}
Line::Line(){
cout << "Object is being created" << endl;
}
int main(){
Line Line;
Line.setlength(10.0);
cout << Line.getlength() << endl;
return 0;
}
- 构造函数也可以带有参数,在创建对象时给对象赋初值
Line Line (double){
cout << "Object is being created, length = " << len << endl;
length = len;
}
int main (){
Line Line(10.0);
cout << Line.getlength <<endl
}
类的析构函数
- 是类的一种特殊的成员函数,在每次删除所创建对象时执行
- 析构函数的名称和类名相同,前面加上~作为前缀
- 没有返回值,不能带有参数
- 作用:在跳出程序前(关闭文件,释放内存)前释放资源
class Line{
public:
Line();
~Line();
};
int main (){
~Line(){
cout << "Object is being deleted" << endl;
}
}
拷贝构造函数
是一种特殊的构造函数,在创建对象时,,使用同一类中 之前创建的对象来初始化新创建的对象。通常用于:
- 使用另一个同类型的对象来初始化新创建的对象
- 复制对象把它作为参数传递给函数
- 复制对象,并从函数返回这个对象
如果类中没有定义拷贝构造函数,编辑器会自己定义一个。如果类中有指针变量,并有动态内存分配,则必须要有一个拷贝构造函数。
基本形式
类名(const 类名 &obj){
....
}//obj是一个对象引用,用于初始化另一个对象的
#include <iostream>
using namespace std;
class Line{
public:
int getlength(void);
Line(int len);
~Line();
Line (const Line &obj);
private:
int *ptr;
};
Line::Line(int len) {
cout << "Object is being creating" <<endl;
//为指针分配内存
ptr=new int ;
*ptr = len;
}
Line::~Line() {
cout << "Object is being deleted" << endl;
delete ptr;
}
int Line::getlength() {
return *ptr;
}
Line::Line(const Line &obj) {
cout << "调用构造函数 并为指针ptr分配内存" << endl;
ptr = new int ;
*ptr = *obj.ptr;//拷贝值
}
void display (Line obj){
cout << "Line的值是" << obj.getlength() <<endl;
}
int main (){
Line Line(10);
display(Line);
return 0;
}
友元函数
友元函数定义在类外部,但有权访问类的private 和 protected成员,友元函数的原型在类的定义中会出现,但友元函数并不是成员函数
友元可以是一个函数,即友元函数;也可以是一个类,即友元类(整个类及其成员都是友元)
需要在类定义中 该函数原型前使用friend关键字表示自己是友方
#include <iostream>
using namespace std;
class box{
double width;
public:
void setwidth(double);
friend void printwidth(box box1);
};
void box::setwidth(double wid) {
width = wid;
}
void printwidth(box box1){
cout << box1.width <<endl;//因为是友军,所以不用借助之前的getwidth()函数,直接用这种当时获得width
}
int main(){
box box1;
box1.setwidth(10.0);
printwidth(box1);
return 0;
}
内联函数
函数功能:以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。因此不适合用内联的情况有:
- 代码很长的(>5)
- 函数内部使用循环语句和双开语句
如果想把一个函数定义为内联函数,要在函数名前面放置关键字inline,在调用函数前就要对函数进行定义
inline int max (int a,int b){
return (a>b)?a:b;
}
int main(){
cout << max(1,2 )<<endl;
return 0;
}
this指针
每个对象都能通过this指针来访问自己的地址,this指针是所有成员函数的隐藏参数,所以在成员函数内部,它可以用来调用对象
- 友元函数没有this指针,因为友元函数不是类的成员,only成员函数才有
#include <iostream>
using namespace std;
class box{
public:
box(double ,double ,double );
double getvolume(void);//计算体积函数
int compare (box box1);
private:
double length;
double breadth;
double height;
};
box::box(double len, double bre, double hei) {//构造函数定义
length=len;
breadth=bre;
height=hei;
}
double box::getvolume() {
return length * breadth * height;
}
int box::compare(box box1) {
return this->getvolume() >box1.getvolume();//注意返回值是int,即返回0或1
}
int main (){
box box1(3.0,4.0,5.0);
box box2(2.0,3.9,2.0);//
if(box1.compare(box2)){//box1调用比较函数,比较函数的形参是box2.函数体内box1通过this指向自己来访问自己的getvolume函数,box2直接调用getvolume函数
cout << "Box2 is smaller than Box1" <<endl;
}
else
{
cout << "Box2 is equal to or larger than Box1" <<endl;
}
return 0;
}
指向类的指针
顾名思义,就是指向类的一个指针。和指向结构体的指针类似,需要用访问运算符-> ,与其他指针一样,在使用前需要对指针进行初始化
#include <iostream>
using namespace std;
class box{
public:
box(double ,double ,double );
double getvolume(void);//计算体积函数
int compare (box box1);
private:
double length;
double breadth;
double height;
};
box::box(double len, double bre, double hei) {//构造函数定义
length=len;
breadth=bre;
height=hei;
}
double box::getvolume() {
return length * breadth * height;
}
int main (){
box box1(3.0,4.0,5.0);
box box2(2.0,3.9,2.0);
box *ptr;
ptr = &box1;//指向对象box1
cout << ptr->getvolume() <<endl;
return 0;
}
类的静态成员
静态成员变量
- 静态成员在类的所有对象中是共享的,可以使用static关键字把类成员定义为静态的。
- 不能把静态成员的初始化放在类的定义中,但是可以在类的外部通过范围解析运算符:: 来重新声明并初始化
#include <iostream>
using namespace std;
class box {
public:
static int objcount;//注意这里要设在public里
box(double ,double ,double );
double getvolume(void);
private:
double length;
double breadth;
double height;
};
int box::objcount = 0;//在类的定义外初始化静态数据成员
double box::getvolume() {
return length * breadth * height;
}
box::box(double l, double b, double h) {
length=l;
breadth=b;
height=h;
objcount++;//每创建一个对象自加
}
int main (){
box box1(1.0,2.0,3.0);
cout << box::objcount << endl;//1
return 0;
}
静态成员函数
如果把函数定义为静态的,就可以把函数与任何特定对象独立开来。静态成员函数即使在类对象不存在的情况下也能被调用,静态函数需要使用 类名 :: 就可以访问。
- 访问范围:可以访问静态成员数据,其他静态成员函数以及类外部的函数
- 静态成员函数有一个类范围,他们不能访问类的this指针