首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么子类引用不能指向父类对象

在java、C++等面向对象的语言中,实现多态的方式就是使用父类引用指向子类对象,所以父类引用指向子类对象是没有任何为题的,但是,大家有没有想过,子类引用可以指向父类对象吗?答案是不可以!...但是为什么呢? 下图是在java中,使用子类引用指向父类对象的情况 ? 编译可以通过,因为对生成的Person对象做了一个强制转换,骗过了编译器,其本质上还是属于子类引用指向父类对象。...为什么java里面不允许这种操作,而C++却允许这种操作呢?我们接下来在C++的环境下,反汇编窥探一下这写代码究竟干了些什么事。...首先,在执行这行代码的时候,先把一个4压入栈中,然后去调用operator new这个函数,很明显,这个4就是该函数的一个参数,它完成的任务就是,向堆空间申请4个字节的存储空间,为什么是4个字节?...这两个赋值操作的反汇编代码如下,可以明显看出,它们都是先找到stu指向的Person对象的堆空间首地址,然后当给age赋值为18时,是把12h(18的十六进制)塞给Person对象首地址位置开始的4个字节

2.4K31
您找到你想要的搜索结果了吗?
是的
没有找到

C++11学习笔记3

右值引用 分类 在古老的标准里,C++中的变量分为左值(lvalue)与右值(rvalue)这两种,左值就是能够用&获得地址的值,可以对他进行修改,右值就是不能用&获得地址的值,通常只是临时变量,不能进行修改...那么现在就应该清楚了,右值引用就是通过对右值进行引用使得我们能够保存这个右值的生命周期,并像使用左值一样的使用右值的方法。(自己的定义) 用途 这么费劲心机定义一个右值引用有啥意义呢?...旧的做法是使用常量引用来做这件事: int main(){ const Test& t=Test(); } 这避免了额外的拷贝,但是后果是这个值只能是常量,无法被修改。...移动拷贝构造 为什么引入移动拷贝构造,这是因为我们考虑到了以下问题: 我们知道,构造函数分为深拷贝和浅拷贝,默认的是浅拷贝,浅拷贝导致的结果就是拷贝出来的对象跟拷贝前的对象拥有相同的堆内元素,如果我们析构了拷贝前的对象...我们可以比较下面的三种方法: 拷贝插入 int main(){ std::vectorv; Test t; v.push_back(t); } 输出: construct

25120

IO流为什么必须手动关闭,不能像其他的对象坐等GC回收?

// 删除文件之前,先将 IO 流关闭 reader.close(); // 删除文件 file.delete(); 可能有的同学会发出疑问,为什么 IO 流必须手动关闭,不能像其他的方法一样坐等...这主要得益于 Java 的虚拟机垃圾回收机制,它可以帮助开发者自动回收内存中的对象,不需要手动释放内存,但是有些东西它是无法回收的,例如端口、显存、文件等,超出了虚拟机能够释放资源的界限。...可能有的同学又发出疑问,我平时本地测试的时候没有发现这个问题,为什么部署到线上就出这个提示的呢?...五、小结 本位主要围绕【为什么 IO 流必须手动关闭,不能像其他的方法坐等 GC 处理】这个话题进行一次内容的整合和总结,同时也给出了推荐的正确关闭 IO 流的写法。...六、参考 1、csdn - 演员12138 - IO流为什么必须手动关闭,不能像其他的方法坐等GC处理 2、csdn - 思想永无止境 - Java之关闭流

61630

1.C与C++

//p3 = &j; 错误,p3的指向不能改变(p3是常量) *p3 = 100; //OK, *p3可以修改 //指向常量常量指针 const int * const...在* 前面,也可以写成 int const *p2 其中,p2的指向可以改变,意味着p2不是常量,但是 *p2不能改变,意味着*p2是常量 所以 上面 const 限定的是 *p2 常量指针 int...* const p3 = &i; // const在*之后 // p3 = &j ; // 错误 p3的指向不能改变(p3是常量) * p3 = 100; // OK,*p3 可以修改 指向常量常量指针...int *const p1) 底层const :指正指向的对象常量(指向常量的指针 const int *p2) 数据类型 struct 和 class #include using...表示对象的集合,其中所有的对象类型必须相同,因为vector 容纳着其他对象,所以被称为容器,vector是一个类模板。

1.1K41

【C++】STL 容器 - vector 动态数组容器 ⑥ ( 使用迭代器遍历 vector 容器步骤 | 获取指容器向首元素的迭代器 begin 函数 | 获取末尾迭代器 | * 迭代器解引用 )

一、 使用迭代器遍历 vector 容器步骤 1、使用迭代器遍历 vector 容器的步骤 使用 迭代器 遍历 vector 容器 , 首先 , 获取 起始范围 迭代器 , std::vector<int...可以用来修改容器中的元素 ; 第二个重载版本函数 是 常量迭代器 , 不能用来修改容器中的元素 ; 返回的迭代器 可以使用 * 操作符进行解引用操作 , 获取迭代器指向的元素的值 ; 代码示例 : #include..."iostream" using namespace std; #include "vector" int main() { // 创建空的 vector 容器 std::vector..."iostream" using namespace std; #include "vector" int main() { // 创建空的 vector 容器 std::vector...容器中的元素也会一并进行修改 ; 特别注意 : operator* 只适用于 非常量迭代器 ; 代码示例 : // 创建空的 vector 容器 std::vector vec

1.3K10

Modern c++快速浅析

const auto cb = a; auto一般情况下会忽略顶层const,保留底层const(顶层const:指针本身是常量,底层const:指针所指对象常量),这点与模板类型推导一致 int*...bool>(result[2]); [c++中为什么不提倡使用vector?]...所有constexpr对象都是const对象,但并非所有的const对象都是constexpr对象 // 都要求编译期常量 int arr[10]; std::array arr; constexpr...更准确的应该将lambda划分为带捕获的lambda以及不带捕获的lambda 在C#这种具备GC机制的语言中,闭包能够延长捕获的变量的生命周期(理解为能够延长生命周期的按引用捕获) 而C++中的按引用捕获并不能延长对象的生命周期...,且按引用捕获会导致lambda表达式包含了对局部对象的引用,这很可能会导致空悬引用 std::function callBack; void pass_vector(const std

15010

基础知识_Cpp

C++中的static关键字的总结 const关键字 特性:(1)被修饰的对象不是常量,是一个只读变量(不能放在case关键字后面也说明const不是一个常量);(2)定义时赋值,之后不允许修改。...---- STL 讲一下类型萃取机制 为什么?...推荐阅读《STL源码剖析》 & 知无涯之std::sort源码剖析 另sort为什么不直接用稳定的堆排序实现?堆排序在排序过程中是跳跃式地访问元素,缓存命中率较低。...= dynamic_cast(r_CBase); // 将基类对象的引用转换派生类对象的引用 3.const_cast(常量转换) 常量指针(或引用)与非常量指针(或引用)之间的转换...int value = 100; const int *cpi = &value; // 定义一个常量指针 //*cpi = 200; // 不能通过常量指针修改值 // 1.

1.9K30

《C++Primer》第七章 类

需要注意的是this是一个常量指针,我们不允许改变this中保存的地址。 const成员函数:上面isbn函数在参数列表之后有一个const关键字,这里const的作用是修改隐式this指针的类型。...默认情况下this的类型是指向类类型非常量版本的常量指针,这意味着默认情况下我们不能把this指针绑定到一个常量对象上。...拷贝:初始化变量;以值的方式传递或返回一个对象 赋值:使用了赋值运算符 销毁:当对象不再存在时执行的操作,比如一个局部对象会在创建它的块结束时销毁,当vector对象或数组销毁时存储在其中的对象也会被销毁...不过很多动态内存的类能(并且应该)使用vector或者string对象管理必要的存储空间,可以避免分配和释放内存带来的复杂性。...因为非常量版本的函数对于常量对象是不可用的,所以我们只能在一个常量对象上调用const成员函数。虽然可以在非常量对象上调用常量版本或者非常量版本,但显然非常量版本是一个更好的匹配。

53420

C++11基础学习系列三

如果想动态操作容器(增加,删除等)或者事先不知道容器的大小,请使用vector。 在使用数组时注意一下几点: 1.数组的维度必须是常量表达式,在编译时是已知的。...()返回结果必须是常量表达式。...由于拷贝大的类型对象或者容器对象比较低效,甚至有的类型(IO类型)是不支持拷贝的,这时我们尽量采用按引用传递,这样可以避免拷贝付出的代价。如果函数内无须改变参数的值时,最好将其声明为常量引用。...return 0; } # 输出为 hEllo 3.通过列表初始化返回多个值 #include #include std::vector<std::string...::cout << i << std::endl; } return 0; } #输出为 hello error 4.返回数组的指针 由于数组不能被拷贝,所以函数不能返回数组,但是可以返回数组的指针或引用

80040

终极 C++避坑指南

为什么这样说呢?const 是 constant 的缩写,翻译成中文就是“常量”,但其实在 C/C++中,const并不是表示“常量”的意思。 我们先来明确一件事,什么是“常量”,什么是“变量”?...所以,我上线才说“C++并不能真正让一个对象提前亡”,这里的std::move就是跟编译器玩了一个文字游戏罢了。...: auto &r1 = 5; // ERR,左值引用不能绑定常量 auto &r2 = GetAnObj(); // ERR,左值引用不能绑定将亡对象 int &&b = 1; auto &r3 = ...那么私有继承既然是用来表示组合关系的,那我们为什么不直接用成员对象呢?为什么要使用私有继承?这是因为用成员对象在某种情况下是有缺陷的。...但是,更多的场景下,我们都会使用std::string类型来保存和处理字符串,因为它功能更强大,使用更方便。得益于隐式构造,我们可以把一个字符串常量轻松转化为std::string类型来处理。

2K20

C++11新特性学习笔记

std::vector ivec1(3, 5); std::vector ivec2 = {5, 5, 5}; std::vector ivec3 = {1,2,3,4,5...返回语句表达式中不能使用非常量表达式的函数、全局数据,且必须是一个常量表达式 常量表达式的构造函数有以下限制: 函数体必须为空 初始化列表只能由常量表达式来赋值 3.7 用户定义字面量(vs2013...::forward可以保存参数的左值或右值特性: #include using namespace std; template void process_value(T & val) { cout...::forward(val) );//C++11中,std::forward可以保存参数的左值或右值特性 } int main() { int a = 0; const int &b = 1;...通过指定它的模板参数,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟执行它们。

2.2K20

C++11新特性学习笔记

ivec1(3, 5); std::vector ivec2 = {5, 5, 5}; std::vector ivec3 = {1,2,3,4,5}; //不使用列表初始化用构造函数难以实现...返回语句表达式中不能使用非常量表达式的函数、全局数据,且必须是一个常量表达式 常量表达式的构造函数有以下限制: 函数体必须为空 初始化列表只能由常量表达式来赋值 3.7 用户定义字面量(vs2013...::forward可以保存参数的左值或右值特性: #include using namespace std; template void process_value(T & val) { cout...::forward(val) );//C++11中,std::forward可以保存参数的左值或右值特性 } int main() { int a = 0; const int &b = 1;...通过指定它的模板参数,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟执行它们。

2K20
领券