类
C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是 C++ 的核心特性,通常被称为用户定义的类型。
类用于指定对象的形式,它包含了数据表示法和用于处理数据的方法。类中的数据和方法称为类的成员。函数在一个类中被称为类的成员。
class Box
{
public:
double length; // 盒子长
double breadth; // 盒子宽
double height; // 盒子高
};
Box Box1;
Box Box2;
#include <iostream>
using namespace std;
class Box
{
public:
double length;
double width;
double height;
// 成员函数声明
double volume(void);
void set(double len, double bre, double hei);
};
// 成员函数定义
double Box::volume(void)
{
return length * width * height;
}
void Box::set(double len, double wid, double hei)
{
length = len;
width = wid;
height = hei;
}
int main()
{
Box Chengdu;
Chengdu.length = 4.0;
Chengdu.width = 6.9;
Chengdu.height = 4.55;
cout << Chengdu.volume();
return 0;
}
成员函数
- 把定义和原型写在类定义内部的函数, 是类的一个成员, 可操作类的任意对象, 可访问对象的所有成员
- 可定义在类内部/范围解析运算符::定义
- 类定义中定义的成员函数将函数声明为内联的(不用inline标识符
class Box
{
public:
double length;
double width;
double height;
double Volume(void)
{
return length * breadth * height;
}
};
/* 或 */
double Box::Volume(void)
{
return length * breadth * height;
}
Box box1; // 创建对象
box1.Volume(); // 调用成员函数
类访问修饰符
- 数据封装: 防止函数直接访问类类型的内部成员
- public: 公有成员
- protected: 受保护成员
- private: 私有成员
公有成员
- 公有成员在程序中类的外部可访问, 可不用任何成员函数来设置/获取公有变量值
class line
{
public:
double length;
void setLength(double len);
double getLength(void);
}
私有成员
- 私有成员变量/函数在类外部不可访问/查看, 仅有类和友元函数可访问私有成员
class Box
{
public:
void setWidth(double wid);
double getWidth(void);
private:
double width;
};
void Box::setWidth(double wid)
{
width = wid;
}
double Box::getWidth(void)
{
return width;
}
保护成员
- 受保护成员类似私有成员, protected成员在派生类(子类)可访问
class Box
{
protected:
double width;
};
class SmallBox:Box // 派生类
{
public:
void setSmallWidth(double wid);
double getSmallwidth(void);
};
void SmallBox::setSmallWidth(double wid)// 子类的成员函数
{
width = wid;
}
double SmallBox::getSmallwidth(void)
{
return width;
}
继承
- 继承: 根据一个类定义另一个类, 简化维护和创建, 重用代码提高效率
- 基类->派生类
- 一个类可派生自多个类
class class2 : class0,class1
- 派生类继承所有基类方法
- 除了: 基类构造函数,析构函数,拷贝构造函数; 重载运算符; 友元函数
class Animal{ // 基类
rat();
sleep();
};
class Dog : public Animl( // 派生类
bark();
)
- public继承: 成员访问属性在派生类不变
- protected继承: 基类public成员访问属性->protected
- private继承: 基类public,protected成员访问属性->private
- 如不写什么继承, 默认private继承
#include<iostream>
#include<assert.h>
using namespace std;
class A{
public:
int a1 = 1;
protected:
int a2 = 2;
private:
int a3 = 3;
};
class B : public A{
public:
void fun(){
// public,protected可被派生类访问
cout << a1 << " " << a2 << endl;
}
};
class C : protected A{
public:
void fun(){
// public->protected可被派生类访问
cout << a1 << " " << a2 << endl;
}
};
class D : private A{
public:
void fun(){
// public->private,protected->private可被派生类访问
cout << a1 << " " << a2 << endl;
}
};
int main(){
B b;
cout << b.a1 << "-"; //正确
// cout << b.a2 << endl; //错误,类外不能访问protected成员
// cout << b.a3 << endl; //错误,类外不能访问private成员
b.fun();
C c;
// cout << c.a1 << endl; //错误, 类外不能访问protected成员
// cout << c.a2 << endl; //错误,类外不能访问protected成员
// cout << c.a3 << endl; //错误,类外不能访问private成员
c.fun();
D d;
// cout << b.a1 << endl; //错误,类外不能访问private成员
// cout << b.a2 << endl; //错误,类外不能访问private成员
// cout << b.a3 << endl; //错误,类外不能访问private成员
d.fun();
system("pause");
return 0;
}
构造&析构函数
构造函数
- 类的一种特殊的成员函数, 在创建类的新对象时执行
- 构造函数名称=类名称, 不返回任何类型(包括void)
- 可用于为某些成员变量设置初始值
#include<iostream>
using namespace std;
class Line
{
public:
void setLength(double len);
double getLength(void);
Line();
// Line(double len); // 带参数的构造函数
private:
double length;
};
Line::Line(void) // 定义成员函数, 包括构造函数
{
cout << "create" << endl;
// length = len;
}
void Line::setLength(double len)
{
length = len;
}
double Line::getLength(void)
{
return length;
}
int main()
{
Line line;
// Line line(10.0);
line.setLength(78.98);
cout << line.getLength();
return 0;
}
初始化列表
Line::Line(double len):length(len)
{}
/* == */
Line::Line(double len)
{
length = len;
}
析构函数
- 析构函数是类的一种特殊成员函数, 每次删除创建的对象时执行
- 与类同名, 不返回不带参数
- 在跳出程序(关闭文件, 释放内存)前释放资源
#include <iostream>
using namespace std;
class Line
{
public:
void setLength(double len);
double getLength(void);
Line();
~Line();
private:
double length;
}
拷贝构造函数
- 拷贝构造函数: 一种特殊构造函数, 创建对象时在使用同一类中之前创建的对象来初始化新创建对象
- 使用另一个同类型对象来初始化新创建对象
- 复制对象作为参数传递给函数
- 复制对象, 从函数返回该对象
#include<iostream>
using namespace std;
class Line
{
public:
int getLength(void);
Line(int len); // 构造函数
Line(const Line &obj); // 拷贝构造函数
~Line(); // 析构函数
private:
int *ptr;
};
Line::Line(int len) // 成员函数定义, 包括构造函数
{
cout << "调用构造函数" << endl;
ptr = new int; // 为指针分配内存
*ptr = len;
}
Line::Line(const Line &obj){
cout << "调用拷贝构造函数,为ptr分配内存" << endl;
ptr = new int;
*ptr = *obj.ptr;
}
Line::~Line(void){
cout << "释放内存" << endl;
delete ptr;
}
int Line::getLength(void){
return *ptr;
}
void display(Line obj){
cout << obj.getLength() << endl;
}
int main(){
Line l1(98.77);
Line l2 = l1;
display(l1);
display(l2);
cout<<"为什么乱码";
return 0;
}
友元函数
- 友元函数: 定义在类外部, 有权访问类的所有private成员和protected成员
- 并非成员函数
- 友元函数
- 友元类: 类所有成员都是友元
#include<iostream>
using namespace std;
class Box
{
double width = 10.89;
public:
double length = 2.4;
friend void printWidth(Box box);// 声明友元
};
void printWidth(Box box) // 不是任何类的成员函数
{
cout << box.width;
}
int main()
{
Box box1;
printWidth(box1);
return 0;
}
内联函数
- 内联函数通常与类一起使用, 编译器把函数的代码副本放在每个调用该函数的地方, 对内联函数任何修改需重新编译函数所有客户端
- inline: 定义内联函数, 若已定义的函数多于一行, 编译器忽略inline限定符
inline int Max(int x, int y)
{
return (x>y)?x:y;
}
this指针
- 每一个对象都可通过this指针访问自己的地址
- this指针是所有成员函数的隐含参数, 成员函数内部可用来指向调用对象
- 友元函数不是成员, 无this指针
- 指向类的指针: ->调用
#include<iostream>
using namespace std;
class Box
{
double length;
double width;
double height;
public:
Box(double len, double wid, double hei)
{
length = len;
width = wid;
height = hei;
}
double Volume()
{
return length * width * height;
}
double Compare(Box box)
{
return this->Volume() > box.Volume();
}
};
int main()
{
Box box1(5.6, 4.6, 99.5);
Box box2(54.4, 40.2, 0.7);
cout << box1.Compare(box2);
}
静态成员
- 静态成员: static,无论创建多少个类的对象, 静态成员只有一个副本
- 在类的所有对象中共享
class Box
{
double length;
double width;
double height;
public:
static int count;
Box(double len, double wid, double hei)
{
length = len;
width = wid;
height = hei;
count++; // 每次创建对象+1
}
};
静态成员函数
- 静态成员函数: 与类的任何对象独立开
- 类对象不存在时也可调用
- 只能访问静态成员数据, 其他静态成员函数, 类外其他函数
- 不能访问类this指针
- 可用于判断某些对象是否被创建
class Box
{
double length;
double width;
double height;
public:
static int count;
Box(double len, double wid, double hei)
{
length = len;
width = wid;
height = hei;
count++; // 每次创建对象+1
}
static int GetCount()
{
return count;
}
};
int Box::count = 0; // 初始化类的静态成员
int main()
{
Box b1(1,2,3);
cout << Box::GetCount() ;
return 0;
}
多态
- 基类的函数被编译器设置为基类版本, 即静态链接
- 在函数前放置virtual, 编译器看到了指针内容, 每个子类都有一个area()的独立实现, 即多态(可有多个不同类, 都带同名但不同实现)
- 虚函数: virtual声明的函数, 派生类中重新定义基类定义的虚函数时, 令编译器不静态链接到该函数, 即动态链接
- 纯虚函数: 基类中不能对虚函数实现
virtual int area() = 0;
class Shape{
protected:
int width, height;
public:
Shape(int a=0, int b=0)
{
width = a;
height = b;
}
virtual int area()
{
cout << "parent";
return 0;
}
};