C++类与对象:类、对象的三大特性、this指针


类是用来描述对象的,对象有什么属性,有什么功能

基本概念

对象:属性(数据)+功能(以函数方式体现)
类:是对 对象的描述

C++中struct和class都能定义类,但两者类中成员的默认访问权限不同

  • struct定义的类默认权限是public
  • class定义的类默认权限是private
  • C和C++中的struct没有可比性,因为两者含义不一样;
    在C++中可以称之为结构体,但基本都称其为类,本质已经不同
  • C语言中,结构体定义出来的变量叫结构体变量;
    C++中结构体定义出来的变量叫对象,结构体也被称为类(类型)

访问权限:限定类中的成员能否直接在类外来使用

public:公有可以在类外直接访问
private:私有不能直接在类外访问
protected:保护不能直接在类外访问

类中所有放置的内容称为当前类的成员:
类中的成员都是声明

成员变量表示对象相关的数据
成员函数描述对象的行为或者功能

注:

  • 成员函数可以定义在成员变量之前(编译器先排查成员变量)
    成员变量是成员函数的全局变量,可以在各成员函数中使用
  • 成员函数可以在类外和类内定义,在类外定义时要在函数返回值后,函数名前加(类名::),不然编译器会将其当做全局函数,函数内部的变量就会在全局作用域中寻找,没有就会报错。
  • 在类里面定义的函数编译器默认是内联函数

调用类中的成员需要通过:对象.成员 的方式调用
在这里插入图片描述

面向对象的三大特性:封装,继承,多态:

类和对象就是 → 封装:

  • 将数据和操作数据的方法进行结合(用类结合);
  • 隐藏对象的属性和实现细节(类中的访问权限),仅对外公开接口来和对象进行交互

类与对象

定义了一个新的类型,就相当于定义了一个新的作用域
类的实例化:用类类型创建对象的过程

  • 类是用来描述对像,
  • 对象是类实例化的结果
  • 类中不能直接放数据,
  • 数据都存放在对象中

类的特殊性质

两个对象d1和d2中的数据不同,调用方法相同,所以每个对象没有必要将函数都保存进去
函数都在代码段保存
如果在定义对象时,对象中还包括相应函数,那么每定义一个对象就会占用许多空间,所以成员函数不存在对象中,对象中只存储数据,方法存储在另外的位置;

那么在调用时,对象应该如何找到相应的方法呢?

  1. 编译器要先对代码进行编译,编译时要将源文件编译(不对头文件编译,预处理会将头文件展开);
  2. 每个源文件编译完后会生成一个 .obj的目标文件,编译器还要将目标文件进行链接(链接的过程就是确定函数地址);
  3. 执行该可执行程序时,就已经得到了函数地址

类的大小

  • 通过sizeof计算一个类,类的大小只和成员变量有关,
  • 也就是说,计算类的大小就是计算类中所有非静态成员变量所占字节数
  • 计算时注意内存对齐

空类的大小:

  • 在主流编译器中(vs/g++),类中只有成员函数而无成员变量和空类的大小都为1个字节;
  • 这是为了防止在开辟空间时,空类创造的不同对象在同一位置,导致编译器无法区分

截取上述部分代码

void SetDate(int year , int month , int day)
{
 	_year = year;
	_month = month;
	_day = day;
}
int main()
{
 	Date d1, d2;
	d1.SetDate(2018,5,1);
 	d2.SetDate(2018,7,1);
 	
 	return0;
}

this指针

类创建一个对象后,该指针就指向当前的对象
因为作用域的问题,对象在主函数中,不能用&对象在类中传参

  • this 指针只能在非静态成员函数中使用,静态成员函数没有隐式的 this 指针
  • this 指针不能被显式地修改,因为它指向的是当前对象,而对象的地址是不能被改变的
  • this是指向当前对象的指针,当一个成员函数被调用时,编译器会自动向成员函数传递一个指向调用该函数的对象的指针
  • return *this; 的形式返回当前对象本身,方便链式调用

this特点:

  1. this相当于引用
  2. this指针的类型:类类型* const,指向不能改变
  3. 只能非静态成员函的内部使用 ;
  4. this指针本质上是一个成员函数的形参,
    对象调用成员函数时,将对象地址作为实参传递给this 形参,所以对象中不存储this指针;
  5. this指针是成员函数第一个隐含的指针形参,(vs环境下)一般情况由编译器通过ecx寄存器自动传递,不需要用户传递;
  6. this的所有操作对用户是透明的,用户不需要来传递,编译器自动完成;
  7. 每个非静态成员函数参数部分就有一个this指针(this是第一个参数)

this指针的空间在栈上:

  • this 指针本身并不是对象的一部分,而是成员函数的一个隐式参数
    因此它通常被实现为一个指向对象内存空间的指针。在大多数情况下,这个指针被分配在调用栈上
  • 无论对象是在栈、堆、全局区上分配的,this 指针只是指向对象所在的内存空间,并不代表 this 指针本身的内存空间
    是由编译器来决定在哪里分配这个指针的内存空间

验证:vs中是不能直接打印this指针的地址(因为指针变量不是左值,&必须是左值才行),应对this指针取别名后,再对该引用的地址进行打印

this指针为空时

在这里插入图片描述

进程虚拟地址空间
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`std::enable_shared_from_this` 是一个模板,其目的是为了解决在一个对象中保存 shared_ptr 的问题。它是 C++11 引入的一个特性。 在使用 `std::shared_ptr` 时,我们往往需要在对象中保存一个 `std::shared_ptr` 的副本,这样才能确保对象在使用完毕后不会被提前销毁。但是这种方式会导致一些问题,比如我们无法防止用户直接使用裸指针来操作对象,从而导致对象被提前销毁等问题。 这时候,我们可以使用 `std::enable_shared_from_this` 来解决这些问题。具体而言,我们需要继承 `std::enable_shared_from_this`,然后在对象中使用 `shared_from_this()` 方法来获取一个指向当前对象的 `std::shared_ptr`。 下面是一个示例代码: ```c++ #include <iostream> #include <memory> class MyClass : public std::enable_shared_from_this<MyClass> { public: std::shared_ptr<MyClass> get_shared_ptr() { return shared_from_this(); } }; int main() { std::shared_ptr<MyClass> p(new MyClass); std::shared_ptr<MyClass> q = p->get_shared_ptr(); std::cout << "p.use_count() = " << p.use_count() << std::endl; std::cout << "q.use_count() = " << q.use_count() << std::endl; return 0; } ``` 在这个示例中,我们定义了一个名为 `MyClass` 的,并且继承了 `std::enable_shared_from_this`。然后,我们在中定义了一个名为 `get_shared_ptr()` 的方法,该方法使用了 `shared_from_this()` 方法来获取一个指向当前对象的 `std::shared_ptr`。在 `main()` 函数中,我们先创建了一个 `std::shared_ptr` 对象 `p`,然后通过 `p` 调用 `get_shared_ptr()` 方法获取了一个指向同一个对象的 `std::shared_ptr` 对象 `q`。最后,我们输出了 `p` 和 `q` 的引用计数,可以看到它们的引用计数都是 2。 需要注意的是,在使用 `std::enable_shared_from_this` 时,我们需要确保对象已经被一个 `std::shared_ptr` 管理,否则使用 `shared_from_this()` 方法会导致程序崩溃。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值