第三章:02类和对象
代码运行环境
本节教程所有代码都是在win11系统,Qt 5.12.12版本,mingw编译工具环境编写运行。创建的工程类型为Qt Console Application。
1.内联成员函数
内联函数的主要目的是为了提高效率
内联函数在编译的时候将代码直接嵌入到调用的地方,从而减少了函数调用的开销。内联函数在编译的时候会导致程序体积变大,这是一种典型的用空间换时间的用法。
内联函数的特点:短小。内联函数仅仅只是给编译器一个提示,若是函数中包含了switch、for等语句,可能编译器不会以内联的方式解析。
内联函数的两种声明方式:
1.在类声明中实现函数
//类是一种用户自定义类型,声明形式:
class //类名称
{
public:
int a; //公有成员
//1.内联函数的实现方式:在类声明中实现函数
int Add (int a, int b )
{
return a + b ;
}
}
2.在.cpp文件中函数实现处添加inline关键字。
//类声明文件 Test.h文件:
class //类名称
{
public:
int a; //公有成员
//1.内联函数的实现方式:在类声明中实现函数
int Add (int a, int b );
}
//类实现文件 Test.cpp文件:
#include "Test.h"
//2.内联函数的实现方法:在.cpp文件中函数实现处添加inline关键字。
inline int Test::Add(int a, int b)
{
return a + b;
}
2.成员函数的重载及其缺省参数
2.1 成员函数的重载
函数的重载要求是要在相同的作用域,成员函数也是如此。
//类声明文件 Test.h文件:
class //类名称
{
public:
int a; //公有成员
//1.内联函数的实现方式:在类声明中实现函数
int Add (int a, int b );
//下面四个函数都在类作用域中,构成成员函数重载
void Init();
void Init(int a);
void Init(int a, int b);
void Init(int a, int b, int c);
//提供一个查看的接口
void Display();
private:
int mA;
int mB;
int mC;
}
//类实现文件 Test.cpp文件:
#include "Test.h"
#include <iostream>
using namespace std;
//2.内联函数的实现方法:在.cpp文件中函数实现处添加inline关键字。
void Test::Init()
{
mA = 0;
mB = 0;
mC = 0;
}
void Test::Init(int a)
{
mA = a;
mB = 0;
mC = 0;
}
void Test::Init(int a, int b)
{
mA = a;
mB = b;
mC = 0;
}
void Test::Init(int a, int b, int c)
{
mA = a;
mB = b;
mC = c;
}
void Test::Display()
{
cout << "a=" << mA << " b=" << mB << " c=" << mC << endl;
}
#include "Test.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Test t;
t.Init();
t.Display();
return a.exec();
}
2.2 成员函数缺省参数
成员函数参数缺省,可以在头文件给出默认的初始值,具体如下。
//头文件
#ifndef QUESHENCANSHU_H
#define QUESHENCANSHU_H
#include <iostream>
using namespace std;
class QueShencanshu
{
public:
QueShencanshu();
//参数缺省时给出默认的初始值
void Init(int a=0, int b=0, int c=0);
// void Init(); 不能再使用这个方法,会出现二义性错误
//提供一个查看的接口
void Display();
private:
int mA;
int mB;
int mC;
};
#endif // QUESHENCANSHU_H
#include "queshencanshu.h"
QueShencanshu::QueShencanshu()
{
}
void QueShencanshu::Init(int a, int b, int c)
{
mA = a;
mB = b;
mC = c;
}
void QueShencanshu::Display()
{
cout << "a=" << mA << " b=" << mB << " c=" << mC << endl;
}
#include <QCoreApplication>
#include "queShencanshu.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QueShencanshu t;
t.Init(); //参数缺省,程序不会报错
t.Display();
return a.exec();
}
3.类与结构体
class(类)与struct(结构体)的区别:在未指定访问权限时,class默认的时私有的,struct默认是公有的。
struct S
{
int X; //公有的
}
Class S
{
int X; //私有的
}
3.1结构体申明与调用
#include <QCoreApplication>
#include <iostream>
using namespace std;
struct Test2
{
int sX;
int sY;
int sZ;
void Init(int x, int y, int z) //结构体中可以有成员函数
{
sX = x;
sY = y;
sZ = z;
}
void Display()
{
cout << "x="<<sX << " y="<<sY <<" z="<<sZ<<endl;
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//C++中申明一个结构体不需要加入struct关键字,因为struct在C++中视作一个类
//在C语言中,结构体声明必须要添加struct关键字
Test2 t;
//测试struct成员函数是否能被调用
t.Init(10,20,30);
t.Display();
//结构体中的成员变量还可以这样初始化
Test2 t2;
t2 = {20,30,40};
t2.Display();
//测试struct成员是否是公有的
cout << t2.sX + t2.sY << endl;
return a.exec();
}
3.2类的申明与调用
#ifndef STRUCTANDCLASS_H
#define STRUCTANDCLASS_H
class StructAndClass
{
//类默认是private的,无法在外部被调用
public: // 将这个注释后,我们程序在申明这个类时调用Init初始化成员变量会出错
StructAndClass();
int sX;
int sY;
int sZ;
void Init(int x, int y, int z) //结构体中可以有成员函数
{
sX = x;
sY = y;
sZ = z;
}
void Display()
{
cout << "x="<<sX << " y="<<sY <<" z="<<sZ<<endl;
}
};
#endif // STRUCTANDCLASS_H
4.隐含的this指针
成员函数有一个隐含的附加形参,即指向该对象的指针,这个隐含的形参叫做this指针。使用this指针保证了每个对象可以拥有不同的数据成员,但处理这些成员的代码可以被所有对象共享。
上面的图片描述了类的中的成员变量与成员函数在构造对象后的不同之处。在实现了两个对象后,我们知道,不同的对象,会为成员变量分配内存空间,但是成员函数是共享的。如何让两个对象在调用类的成员函数时进行区分,这就需要this指针。this指针是指向对象自身的指针上图中的函数调用实际上是下面的方式。
具体代码如下:
#include "queshencanshu.h"
QueShencanshu::QueShencanshu()
{
}
void QueShencanshu::Init(int a, int b, int c)
{
mA = a; //这段代码等价于 this->mA = a;
mB = b;
mC = c;
}
void QueShencanshu::Display()
{
cout << "a=" << mA << " b=" << mB << " c=" << mC << endl;
}