欢迎光临
我们一直在努力

C++ 第 39 章: 阶段性总复习——类、对象、构造、继承、this、指针与智能指针

39.1 从变量到对象

最初:

double angle = 30;
double speed = 10;

数据散着放。

后来:

struct Joint
{
double angle;
double speed;
};

把相关数据组合。

再后来:

class Joint
{
public:
void setAngle(double angle)
{
this->angle_ = angle;
}

private:
double angle_ = 0.0;
};

变成:

对象
=
数据
+
操作这些数据的函数

所以一个:

Joint j;

对象可以粗略画成:

j
┌────────────────────┐
│ angle_ │
│ │
│ setAngle() │
└────────────────────┘


39.2 class 和对象不是一回事

class Joint
{
…
};

是:

类型/设计规则。

而:

Joint j;

才是:

创建具体对象。

对应:

class
= 图纸

object
= 按图纸造出来的东西


39.3 构造函数不是“造对象的命令”

class Robot
{
public:
Robot()
{
}
};

这里只是定义:

Robot 对象出生的时候怎么初始化。

真正:

Robot robot;

才开始创建对象。

过程:

Robot robot;
↓
需要创建一个Robot对象
↓
准备对象存储空间
↓
调用Robot()
↓
对象初始化
↓
robot可以使用


39.4 初始化列表

例如:

class Robot
{
public:
Robot(int id)
: id_(id)
{
}

private:
int id_;
};

Robot robot(3);

过程:

参数 id = 3
↓
创建 robot
↓
直接初始化成员 id_ = 3
↓
执行 {}

所以:

: id_(id)

不是赋值语句,而是:

初始化成员。


39.5 继承

class Child : public Parent

表示:

Child 是 Parent 的派生类。

一个 Child 对象包含:

Child对象
┌───────────────────┐
│ Parent父类部分 │
├───────────────────┤
│ Child自己的部分 │
└───────────────────┘

于是:

class NumberPublisher : public rclcpp::Node

表示:

NumberPublisher对象
┌────────────────────────┐
│ rclcpp::Node部分 │
├────────────────────────┤
│ publisher_ │
│ timer_ │
│ count_ │
└────────────────────────┘


39.6 父类构造

NumberPublisher()
: Node("number_publisher"),
count_(0)

意味着:

创建NumberPublisher
↓
先调用Node构造函数
Node("number_publisher")
↓
初始化count_=0
↓
执行NumberPublisher构造函数体

注意:

Node("number_publisher")

不是另外造一个没关系的 Node。

它是在构造:

当前 NumberPublisher 对象内部的 Node 父类部分。


39.7 this 到底是什么

只要你正在:

某个对象.成员函数()

那么这个成员函数内部就隐含一个:

this

它指向:

当前对象。

例如:

Joint j1;
j1.setAngle(30);

进入:

void setAngle(double angle)

之后:

this
↓
j1

于是:

this->angle_

就是:

j1自己的angle_


39.8 this 不是对象里的普通成员变量

不要画成:

Joint
├── angle_
└── this ×

更合适理解:

调用成员函数时
C++偷偷额外告诉函数:
“当前对象地址在这里。”
↓
this

这是以后理解成员函数非常关键的模型。


39.9 this 和继承

this->create_publisher(…)

时:

this
↓
当前NumberPublisher对象
↓
寻找create_publisher
↓
NumberPublisher自己没有
↓
父类Node有
↓
调用Node提供的函数

所以继承的功能不需要把源码重新写进子类。

子类对象能够使用继承得到的成员接口。


39.10 public / private

例如:

class Joint
{
public:
void setAngle(double angle)
{
angle_ = angle;
}

private:
double angle_;
};

外部:

j.angle_ = 30; // 不允许

但是:

j.setAngle(30); // 允许

然后类内部:

angle_ = angle;

允许。

所以封装逻辑:

外部
↓
public接口
↓
类内部逻辑
↓
private数据


39.11 对象与指针

直接对象:

Robot robot;

访问:

robot.run();

因为:

robot
= 对象


指针:

Robot* p = &robot;

此时:

p
↓
robot对象

访问:

p->run();

所以锁死:

对象 .
指针 ->


39.12 指针最根本的作用

现阶段你只需要一句:

指针主要解决“我怎么找到另一个对象”。

它不是:

数据运输管道。

例如:

publisher_->publish(msg);

不是:

msg进入publisher_这个指针

而是:

publisher_
↓
找到Publisher对象
↓
调用Publisher对象的publish()
↓
把msg作为函数参数传进去


39.13 智能指针

裸指针:

Robot* p;

重点是:

保存地址。

智能指针:

std::shared_ptr<Robot>

除了可以找到对象,还:

参与管理对象生命周期。

创建:

auto p = std::make_shared<Robot>();

含义:

创建Robot对象
+
创建shared_ptr管理这个对象
+
把智能指针返回给p

所以不是“只有指针没有对象”。

对象真实存在。


39.14 make_shared

例如:

auto node =
std::make_shared<NumberPublisher>();

可以拆成三个概念:

NumberPublisher
→ 要创建的对象类型

make_shared
→ 创建对象并用shared_ptr管理

node
→ 得到的智能指针变量

关系:

node
│
▼
NumberPublisher对象


39.15 node、this、publisher_ 都是指针,但角色不同

这是目前最重要的表:

名字指向谁用来干什么
node NumberPublisher 对象 main() 找到并管理整个节点对象
this 当前 NumberPublisher 对象 成员函数知道“我正在操作哪个对象”
publisher_ Publisher 对象 NumberPublisher 找到自己的发布器
timer_ Timer 对象 NumberPublisher 找到自己的定时器

所以:

都是“指向对象”,但它们指向的对象完全不同。


39.16 Lambda

[this]()
{
publishNumber();
}

分成:

[this]

捕获列表:

让 lambda 记住当前对象的 this 指针。

()

参数列表:

没有参数。

{
publishNumber();
}

函数体:

调用当前对象的成员函数。

所以 Timer 保存这个 lambda 后:

Timer到时间
↓
执行lambda
↓
lambda拿到this
↓
找到NumberPublisher
↓
调用publishNumber()


39.17 本章最终对象图

main()

node
│
│ shared_ptr
▼
┌───────────────────────────────┐
│ NumberPublisher对象 │
│ │
│ Node父类部分 │
│ │
│ count_ │
│ │
│ publisher_ ──────────────┐ │
│ │ │
│ timer_ ──────────────┐ │ │
└──────────────────────│───│────┘
│ │
▼ ▼
Timer Publisher
对象 对象

Timer
│
└─保存lambda
│
└─保存this
│
└────→ NumberPublisher对象

这一张图就是第 39 章核心。

赞(0)
未经允许不得转载:171主机测评 » C++ 第 39 章: 阶段性总复习——类、对象、构造、继承、this、指针与智能指针
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址