c++

【C++基础】面向对象

Posted by 卢小胖 on 2021-09-13
Estimated Reading Time 7 Minutes
Words 1.8k In Total
Viewed Times

类&对象

一个普普通通的类:

class Box{

// 私有成员
private:
double length;
double width;
// 公共成员
public:
int size;

// 内部定义成员函数
double getV(){
return length*width;
}

// 外部定义成员函数
void setLength(double _length);
void setWidth(double _width);
};

// 外部定义成员函数
void Box::setLength(double _length){
length = _length;
}

void Box::setWidth(double _width){
width = _width;
}

调用:

Box box;
box.setLength(100);
box.setWidth(20);

修饰符

常见的有私有(private)和public(公共)修饰符,还有一个保护(protected)成员:

在Box类中加入一个保护成员:

protected:
int age;

派生类:

// 派生类
class SmallBox:Box
{

public:
void setSmallAge(int _age);
int getSmallAge();

};

void SmallBox::setSmallAge(int _age){
age = _age;
}

int SmallBox::getSmallAge(){
return age;
}

  • 保护成员和私有成员相似,外部对象不可以访问,其派生类可以访问。

  • 派生类可以访问父类的公共成员,不可访问私有成员

类构造函数

构造函数用于创建该对象,并赋予初始值。

Box类的构造函数也可以理解成返回Box类型的成员方法,同样需要在类中定义,在内部或者外部实现。

// 公共成员
public:
int size;
// 构造函数:
Box();
Box(double _length,int _size);
//Box(double _length,int _age);

实现:

// 构造函数
Box::Box(){

}

Box::Box(double _length,int _size){
length = _length;
size = _size;
}

//错误,与上一个冲突
Box::Box(double _length,int _age){
length = _length;
age = _age;
}

使用:

Box box1(12,12);
cout << "box1:" << box1.size << endl;

析构函数

类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。

析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。

public:
// 析构函数:
~Box();

// 析构函数
Box::~Box(){
cout << "box deleted" <<endl;
}

我们在对象删除的时候打印,查看是否执行了析构函数。

友元函数

友元函数使用friend修饰符修饰,不仅仅是函数,对类同样有效,成为友元类。

我们在类外部定义一个普通函数:

void printSth(Box box){
// 在Box类中设置了友元函数,所以能访问Box的所有成员
cout << "friend:" << box.length << endl;
}

在Box类中加入并使用friend修饰:

class Box{

// 私有成员
private:
double length;
double width;
// 公共成员
public:
// 友元函数
friend void printSth(Box box);

// 派生成员
protected:
int age;
};

友元函数能够访问该类的私有成员和保护成员。

参考:https://www.cnblogs.com/balingybj/p/4778247.html

内联函数

和kotlin中内联函数相似

// 内联函数
inline int Max(int i,int j){
return i >= j ? i : j;
}

this指针

指向本类或者该函数的地址,用来调用自身成员。

void prin(){
cout << this->length <<endl;
}

友元函数没有this指针,因为其不是类的成员,只有成员函数才有this指针。

类指针

指向类成员的指针,使用->来使用其类成员

Box box;

// 类指针
Box *ptrBOX;
ptrBOX = &box;

//使用
cout << ptrBOX->size <<endl;

static静态

静态成员

  • 对于类的静态成员来说,无论有多少个对象,只存在一个静态成员副本。
  • 静态成员在所有类对象中是共享的。
  • 每次创建新的类对象,需要注意静态成员值的变化。
private:
static int money;

在类外部进行初始化:

// 静态成员初始化
int Box::money = 10;

以下展示了静态成员在创建多个类对象时候的变化:

class Box
{
private:
static int money;
// 初始化次数
static int initCount;
public:
void setMoney(int _money){
this->money = _money;
}
int getMoney(){
cout << "init:"<<initCount<<" money:"<<money <<endl;
return money;
}
Box(){
initCount++;
}
// 静态函数
static int getCount(){
return initCount;
}
};


输出:
init:1 money:1
init:2 money:1

静态函数

创建一个静态函数:

// 静态函数
static int getCount(){
return initCount;
}

静态函数不能访问类的非static成员,所以也不能使用this指针。

静态函数是在编译期就存在的,所以不需要类的对象就可以调用:

Box box;

//调用方法:
Box::getCount()
box.getCount()

参考:https://www.w3cschool.cn/cpp/cpp-classes-objects.html

继承

创建一个基类:

class Base
{
private:
int i;
public:
int j;
protected:
int k;
};

继承类,也成为派生类

class Activity : Base
{
private:

public:
int getJ(){
return j;
}
int getK(){
return k;
}

};

派生类能访问基类的public、protected成员,无法访问private成员。

比如上述在获取i成员会报错:


int getI(){
return i;
}

派生类的多种类型:

  • 公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员来访问。
  • 保护继承(protected): 当一个类派生自保护基类时,基类的公有和保护成员将成为派生类的保护成员。
  • 私有继承(private):当一个类派生自私有基类时,基类的公有和保护成员将成为派生类的私有成员。
// 继承类型
class test: public Base{

};

class test2: protected Base{

};

class test3: private Base{

};

多继承

class test4 : Base,test2{

};

class test5 : public Base,private test2,protected test3{

};

封装

省略…

多态

同一个类的不同对象在不同情况下有不同的表现

#include <iostream>
using namespace std;

class Shape{
private:
int length;
int width;
public:
int area(){
cout << "Shape" << endl;
}
};

class Rectangle : public Shape{
public:
int area(){
cout << "Rectangle" << endl;
}
};


int main(){

Shape *shape;
Rectangle rec;

shape = &rec;
shape->area();

system("pause");
return 0;
}

上述代码输出:Shape,也就是执行了Shape类中的area方法,并没有执行派生类方法。

因为 *shape指针定义为Shape类型,area方法在编译器已经存在,所以执行的是编译器时候的area方法。

cpp中引入了虚函数来解决多态问题,virtual关键字,在基类acre方法中更改:

class Shape{
private:
int length;
int width;
public:
virtual int area(){
cout << "Shape" << endl;
}
};

输出结果:Rectangle

除此之外,还可以将virtual函数设为空实现,成为纯虚函数

// 纯虚函数
// virtual int area() = 0;

参考:https://www.w3cschool.cn/cpp/cpp-polymorphism.html

接口

cpp中没有接口,只有抽象类,只要一个类有virtual修饰的纯虚函数,就成为抽象类。

cpp抽象类特点:

  • 无法实例化,必须由子类实例化。
  • 在实际中为了强调一个类是抽象类,可将该类的构造函数说明为保护(protected)的访问控制权限。
  • 派生类必须实现抽象类的纯虚函数,如果没有,则派生类也是一个抽象类.(虚函数则不收影响)