函数形参为基类数组,实参为继承类数组,下存在的问题------c++程序设计原理与实践(进阶篇)
示例:
#include<iostream>
using namespace std;
class A {
public:
int a;
int b;
A(int aa=1, int bb=2):a(aa),b(bb) {}
};
class B :public A {
public:
B(int a=3,int b=4,int c=5,int d=6):A(a,b),d(c),g(d) {}
int d;
int g;
}; void f(A* p,int n) { for (int i = 0; i < n;i++)cout << p[i].a<<" "; }
int main() { A a1[50];
B b1[50];
f(a1, 50);
cout << endl;
f(b1, 50); }
输出结果:
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
3 5 3 5 3 5 3 5 3 5 3 5 3 5 3 5 3 5 3 5 3 5 3 5 3 5 3 5 3 5 3 5 3 5 3 5 3 5 3 5 3 5 3 5 3 5 3 5 3 5
问题出现在&b1[0]是一个B*指针。f()期待的是一个A*指针,而我们传递给它的是一个A派生类对象指针(B*)。这显然是允许的。但是f()不仅仅把A*作为一个指针类使用,还将它作为数组来使用,通过下标访问其元素:
for (int i = 0; i < n;i++)cout << p[i].a<<" ";
这段代码顺序访问内存地址&p[0]、&p[1]、&p[2]···上的对象:

就内存地址而言,这些指针的间距为sizeof(A)。但不幸的是,对于此次f()的调用,sizeof(B)大于sizeof(A),因此内存布局如下所示:

也就是说,f()中指针实际指向的是B对象的中间!刚好B是4个int,A是2个int。所以才有上述的输出。如果不是刚好,这很可能导致程序崩溃。
c++程序设计原理与实践(进阶篇)
函数形参为基类数组,实参为继承类数组,下存在的问题------c++程序设计原理与实践(进阶篇)的更多相关文章
- 函数返回值string与返回值bool区别------c++程序设计原理与实践(进阶篇)
为什么find_from_addr()和find_subject()如此不同?比如,find_from_addr()返回bool值,而find_subject()返回string.原因在于我们想说明: ...
- C++浅析——继承类内存分布和虚析构函数
继承类研究 1. Code 1.1 Cbase, CTEST为基类,CTest2为其继承类,并重新申明了基类中的同名变量 class CBase { public: int Data; CBase() ...
- c#实例化继承类,必须对被继承类的程序集做引用
0x00 问题 类型“Model.NewModel”在未被引用的程序集中定义.必须添加对程序集“Model, Version=1.0.0.0, Culture=neutral, PublicKeyTo ...
- c#实例化继承类,必须对被继承类的程序集做引用 .net core Redis分布式缓存客户端实现逻辑分析及示例demo 数据库笔记之索引和事务 centos 7下安装python 3.6笔记 你大波哥~ C#开源框架(转载) JSON C# Class Generator ---由json字符串生成C#实体类的工具
c#实例化继承类,必须对被继承类的程序集做引用 0x00 问题 类型“Model.NewModel”在未被引用的程序集中定义.必须添加对程序集“Model, Version=1.0.0.0, Cu ...
- python学习道路(day4note)(函数,形参实参位置参数匿名参数,匿名函数,高阶函数,镶嵌函数)
1.函数 2种编程方法 关键词面向对象:华山派 --->> 类----->class面向过程:少林派 -->> 过程--->def 函数式编程:逍遥派 --> ...
- C++ primer(十三)--类继承、构造函数成员初始化、虚函数、抽象基类
一.基类 从一个类派生出另一个类时,原始类称为基类,继承类称为派生类. 派生类对自身基类的private成员没有访问权限,对基类对象的protected成员没有访问权限,对派生类对象的(基类之 ...
- c++之函数形参和实参
c++之函数形参和实参讲解 1.非地址型参数 在c++中实现模块化编程时,我们形成会遇到对自定义的函数模块传入参数的操作,即形参.这里主要讲解一个非地址型的形参. 不多说,先看代码: #include ...
- 虚函数的使用 以及虚函数与重载的关系, 空虚函数的作用,纯虚函数->抽象类,基类虚析构函数使释放对象更彻底
为了访问公有派生类的特定成员,可以通过讲基类指针显示转换为派生类指针. 也可以将基类的非静态成员函数定义为虚函数(在函数前加上virtual) #include<iostream> usi ...
- RTTI、虚函数和虚基类的实现方式、开销分析及使用指导(虚函数的开销很小,就2次操作而已)
白杨 http://baiy.cn “在正确的场合使用恰当的特性” 对称职的C++程序员来说是一个基本标准.想要做到这点,首先要了解语言中每个特性的实现方式及其开销.本文主要讨论相对于传统 C 而言, ...
随机推荐
- Spring MVC启动时初始化的几个常用方法
Spring-MVC的应用中,要实现类似的功能,主要是通过实现下面这些接口(任选一,至少一个即可) 一.ApplicationContextAware接口 +? 1 2 3 4 5 6 7 8 9 p ...
- C#使用自定义字体
/// <summary> /// 设置字体 /// </summary> /// <param name="path">字体文件路径,包含字体 ...
- timequest学习之黑金动力(一)
黑金动力的资料还是非常有价值的.通过建模篇,对于给定的时序关系,我总能实现.但是,这总是很初级的能力.也只是为后面的建模服务.所以,现阶段我的能力还是非常有限.我相信我一定会成为牛人,能够独挡一面.借 ...
- python's thirty-first day for me re模块
正则表达式: re 模块 可以读懂 你写的正则表达式,根据你写的表达式去执行任务. 正则表达式:字符串的操作. 使用一些规则来检测字符串是否符合我的要求 —— 表单验证 从一段字符串中找到符合我要 ...
- Python函数的进阶
一 函数的动态参数 *agrs 位置参数动态传参 *args 接收多个位置参数 def func(*args): print(args) func("女儿国","西 ...
- Oracle DATABASE LINK(DBLINK)创建
数据库全局名称可以用以下命令查出: SELECT * FROM GLOBAL_NAME; 修改可以用以下语句来修改参数值: ALTER SYSTEM SET GLOBAL_NAME=TRUE/FALS ...
- 动态规划——最长不下降子序列(LIS)
最长不降子序列是这样一个问题: 下面介绍动态规划的做法. 令 dp[i] 表示以 A[i] 结尾的最长不下降序列长度.这样对 A[i] 来说就会有两种可能: 如果存在 A[i] 之前的元素 A[j] ...
- 【原创】6. 在MYSQL++中实现SQL语法中的NULL
这次要说明的是在MYSQL++中为了实现SQL中的NULL而做出的一系列的举措.我的感觉是Null<T, B>类型通常出现在SSQLS和template Query中比较多. 1. 什么是 ...
- codeforce469DIV2——D. A Leapfrog in the Array
题意: 给出1<=n<=10^18和1<=q<=200000,有一个长度为2*n-1的数组,初始时单数位置存(i+1)/2,双数位置是空的.每次找出最右边的一个数将它跳到离它最 ...
- vmware workstation + kvm 部署
1.物理机BIOS设置里开启虚拟化功能 2.vm里面开启一下两个功能 3.找到存放该虚拟机的dir,找到以.vmx结尾的文件,增加一行 apic.xapic.enabled = "FALSE ...