类和对象

c++对象模型和this指针

成员变量和成员函数分开存储

在c++中类内的成员变量和成员函数分开存储
只有非静态成员变量才属于类的对象

#include<iostream>
using namespace std;class Person {};
class Demo {int m_A;//非静态成员变量属于对象上
};
class Student {//非静态成员函数void sayHello() {}
};class Work {static int a;static void sayHello() {cout << "你好呀" << endl;}
};
int Work::a = 10;
void test01() {Person p;//在c++中,为了区别不同的空对象,编译器为其赋了一个字节的存储空间cout << sizeof(p) << endl;//1Demo d;cout << sizeof(d) << endl;//4   非静态成员变量属于对象上Student s;cout << sizeof(s) << endl;//1   非静态成员函数不在对象上Work w;cout << sizeof(w) << endl;//1  静态变量不在对象上
}
int main() {test01();system("pause");return 0;
}

this指针

  • this指针指向被调用的成员函数所属的对象
  • this指针是隐含每一个非静态成员函数内的一种指针
  • this指针不需要定义,直接调用即可

this指针的作用

当形参和成员变量相同时,可用this指针来区分
在类的非静态成员函数中返回对象本身,可以使用 return * this;

注意事项: 如果返回的只是单纯的类名,则创建的是一个新的对象,只有返回引用才是返回对象本身

#include<iostream>
using namespace std;class Person {public:int age;Person(int age) {//this指向成员变量或成员函数被调用的对象this->age = age;}//如果返回的是一个引用,则返回的是本身Person& personAddAge(Person& person) {this->age += person.age;//this指向p2的指针,而*this指向p2这个对象本体return *this;}//如果返回的是一个对象,则相当于创建了一个新的对象,而本身所变的只会自身操作函数一次,后续为新的对象再进行函数内操作Person personAddAge1(Person& person) {this->age += person.age;//this指向p2的指针,而*this指向p2这个对象本体return *this;}
};void test01() {Person p(18);cout << "p的年龄为" << p.age << endl;
}void test02() {Person p1(10);Person p2(10);Person p3(10);p2.personAddAge(p1).personAddAge(p1).personAddAge(p1);p3.personAddAge1(p1).personAddAge1(p1).personAddAge1(p1);cout << "p2的年龄为:" << p2.age << endl;//40cout << "p3的年龄为:" << p3.age << endl;//20
}
int main() {test01();//18test02();system("pause");return 0;
}

空指针访问成员函数

c++中空指针也是可以调用this指针的,但是也要注意有没有用到this指针
如果用到this指针,需要加以判断保证代码的健壮性

#include<iostream>
using namespace std;class Person {public:int m_Age;void showClass() {cout << "这是小学一年级" << endl;}void showAge() {//对this做判空处理,增强代码的健壮性,防止空指针带来的异常if (this == NULL) {return;}cout << "你的年龄" << this->m_Age << endl;}};void test01() {//创建一个空指针Person* p = NULL;p->showClass();//空指针可以调用成员函数p->showAge();//由于空指针直接调用导致程序崩溃 解决方案,在成员函数中,对this多加一层判断}int main() {test01();system("pause");return 0;
}

const修饰成员函数

常函数

  1. 成员函数后加上const后我们称这个函数为常函数
  2. 常函数内不可以修改成员属性
  3. 只有在成员属性声明时加上关键字mutable,才可以在常函数内进行修改

常对象

  1. 声明对象前加const,称声明对象为常对象
  2. 常对象只能调用常函数

常函数修改成员属性报错示例:

常对象修改成员属性报错示例:

常对象只能调用常函数

常函数和常对象调用示例代码:

#include<iostream>
using namespace std;
class P {public:int m_A;mutable int m_B; // mutable 修饰的成员属性可以在常函数进行修改//常函数void changeValue() const{//this->m_A = 200;m_B = 20;}void func() {}
};void test01() {P p;p.changeValue();
}
void test02() {//在对象前加上关键字const修饰,变为常对象const P p;//p.m_A = 20;p.m_B = 30;//被mutable修饰的成员属性,在常对象下也可以进行修改//p.func(); //常对象不可以调用普通的成员函数,因为普通的成员函数可以修改成员属性p.changeValue();
}
int main() {test01();test02();system("pause");return 0;
}

友元

目的

让一个函数或者一个类访问另一个类的私有成员

关键字

friend

实现

  1. 全局函数做友元
  2. 类做友元
  3. 成员函数做友元

1 全局函数做友元需要在对应类中声明

#include <iostream>
using namespace std;
//全局函数做友元class Building {//全局函数goodFriend()作为Building类的好朋友,可以访问Building的私有成员friend void goodFriend(Building* b);
public:Building() {m_LivingRoom = "客厅";m_BedRoom = "卧室";}
public:string m_LivingRoom;
private:string m_BedRoom;
};//全局函数
void goodFriend(Building * b) {cout << "好朋友正在访问" << b->m_LivingRoom << endl;cout << "好朋友正在访问" << b->m_BedRoom << endl;  //访问私有成员
}void test01() {Building b;goodFriend(&b);
}
int main() {test01();system("pause");return 0;
}

2 类做友元也需要在对应类内部声明

#include <iostream>
using namespace std;
//类做友元class Building {//GoodFriend作为Building的友元,可以访问Building的私有成员friend class GoodFriend;
public:Building();public:string m_LivingRoom;
private:string m_BedRoom;
};class GoodFriend {public:GoodFriend();void visit(); //参观函数,用来访问Building的成员Building* b;
};//类外实现成员函数
Building::Building() {m_LivingRoom = "客厅";m_BedRoom = "卧室";
}GoodFriend::GoodFriend() {b = new Building;
}
void GoodFriend::visit() {cout << "好朋友正在访问" << b->m_LivingRoom << endl;cout << "好朋友正在访问" << b->m_BedRoom << endl;
}
void test01() {GoodFriend g;g.visit();}
int main() {test01();system("pause");return 0;
}

3 成员函数做友元
这里解释一个问题,为什么不能把Buiding写在GoodFriend上,为什么会报错。
因为在Building中声明了visit()是Building的友元,固然可以在Building前面提前声明GoodFriend类,但不能在类外声明方法,故将GoodFriend声明在Building前面,并不能获取到实际的方法,在定义方法时,编译器无法把visit()这个成员函数当作Building的友元函数,故无法访问Building类的私有成员(个人理解,如果有更好的理解欢迎评论)

#include <iostream>
using namespace std;
//成员函数做友元
class Building;
class GoodFriend {public:GoodFriend();void visit(); //参观函数,用来访问Building的成员void visit2(); //参观函数2,不能访问Building的私有成员
private:Building* b;
};
class Building {friend void GoodFriend::visit();
public:Building();public:string m_LivingRoom;
private:string m_BedRoom;
};
//类外实现成员函数
Building::Building() {m_LivingRoom = "客厅";m_BedRoom = "卧室";
}GoodFriend::GoodFriend() {b = new Building;
}
void GoodFriend::visit() {cout << "1好朋友正在访问" << b->m_LivingRoom << endl;cout << "1好朋友正在访问" << b->m_BedRoom << endl;
}
void GoodFriend::visit2() {cout << "2好朋友正在访问" << b->m_LivingRoom << endl;/*cout << "好朋友正在访问" << b->m_BedRoom << endl;*/
}
void test01() {GoodFriend g;g.visit();g.visit2();}
int main() {test01();system("pause");return 0;
}

c++学习13 类与对象(二)c++对象模型和this指针和友元相关推荐

  1. C++阶段03笔记02【类和对象(封装、对象的初始化和清理、对象模型和this指针、友元、运算符重载、继承、多态)】

    C++| 匠心之作 从0到1入门学编程[视频+课件+笔记+源码] 目录 1.内存分区模型 2.引用 3.函数提高 4.类和对象 4.1.封装 4.1.1.封装的意义 --实例1:设计圆类 --实例2: ...

  2. 第三层:C++对象模型和this指针

    文章目录 前情回顾 C++对象模型和this指针 类成员变量和类成员函数的储存 this指针 this指针概念 this指针用途 用途1解释 用途2解释 空指针调用成员函数 const修饰的成员变量 ...

  3. 类和对象- C++对象模型和this指针- 成员变量和成员函数分开存储

    成员变量和成员函数分开存储 在C++中,类内的成员变量和成员函数分开存储 只有非静态成员变量才属于类的对象上 空对象占用内存空间 class Person {};void test01() {Pers ...

  4. 【C++编程语言】之C++对象模型和this指针

    目录 1.成员变量和成员函数分开存储 2.this指针概念 3.空指针访问成员函数 4.const修饰成员函数 1.成员变量和成员函数分开存储 ​ 在C++中,类内的成员变量和成员函数分开存储,只有非 ...

  5. 【C++笔记】对象模型和this指针

    一.成员变量和成员函数分开存储 C++中,类内的成员变量和成员函数分开存储,只有非静态成员变量才属于类的对象 空对象也会占用内存 C++编译器会给每个空对象也分配一个字节空间,是为了标志此对象占内存的 ...

  6. C++基础知识 —— 内存分区模型、引用、函数重载、类和继承、this指针、友元、多态、文件操作

       参考 黑马程序员 C++课程笔记,个人理解及整理  可以使用 在线编译c++代码 来简单验证.学习代码 目录 C++核心编程 1. 内存分区模型 1.1 程序运行前 1.2 程序运行后 1.3 ...

  7. 十八、可迭代对象、迭代器对象和生成器

    可迭代对象.迭代器对象和生成器 一 可迭代对象 二 迭代器对象 三 迭代器优缺点 三 for循环原理 四 异常处理 4.1 什么是异常 4.2 异常操作 4.2.1 语法 4.2.2 实际操作 4.2 ...

  8. Kotlin学习笔记 第二章 类与对象 第十二 十三节 对象表达式与对象声明 类型别名

    参考链接 Kotlin官方文档 https://kotlinlang.org/docs/home.html 中文网站 https://www.kotlincn.net/docs/reference/p ...

  9. python class object_【python系统学习13】类(class)与对象(object)

    目录: 类(class)和实例 类 整数.字符串.浮点数等,不同的数据类型就属于不同的类. 想想看当初学数据类型,我们用type验证数据类型后打印的结果 忘了就再来看看: strs = '字符串' i ...

最新文章

  1. 螳螂捕蝉黄雀在后!地下黑客论坛免费远控木马被曝“后门”
  2. JVM内存状况查看方法和分析工具
  3. python面试-python面试问题集锦
  4. mybatis教程--延迟加载详解
  5. 转行学python后悔_月薪13k的我为什么要转行学Python?
  6. .Net应用之数据连接(少儿助学网MisDataSet.dll)原代码
  7. qt int转换成qstring_「QT界面编程实例」创建颜色下拉框并改变窗体颜色(调色板)...
  8. 【操作系统】请求调页
  9. python快速入门步骤_Python快速入门
  10. android自助终端界面源码_这些安卓源码调试技巧,不懂的程序员月薪绝对不过 30k...
  11. mysql怎么实现的主从复制_【mysql】mysql实现主从复制
  12. 优秀!Github上10个开源免费的后台控制面板你值得拥有!
  13. EC读书笔记系列之18:条款47、48
  14. 【UVA1599】Ideal Path理想路径--两种约束条件(!!双向bfs+非简单图的最短路+无向图邻接记录法)
  15. C++二维vector初始化
  16. 51单片机led灯依次点亮
  17. adb 静默安装_apk 静默安装
  18. 长沙.NET技术社区正式成立
  19. RabbitMQ之延迟队列
  20. Kubernetes(k8s)的Pod资源清单spec.containers属性详细讲解

热门文章

  1. 配置nginx使其支持pathinfo路径模式
  2. 一个大专Java程序员的自述
  3. Crypto++入门学习笔记(DES、AES、RSA、SHA-256)(转)
  4. 魅k30什么时候出鸿蒙系统,红米K30什么时候上市
  5. Illustrator 教程:如何在 Illustrator 中修改形状?
  6. Xamarin 可能的替代者.NET MAUI
  7. 微信小游戏开发(3)
  8. 物理层传输格式的用法,关于TF,TFS,TFC,TFCS,TFI,TFCI
  9. 程序员如何准备好一次面试
  10. 〖编程初学者的自我修养 - 优质简历篇①〗- 知己知彼,面试官是如何分析一份简历的