大家好,又见面了,我是你们的朋友全栈君。...在与服务器交互的时候,我们往往会使用json字符串,今天的例子是java对象转化为字符串, 代码如下 protected void onCreate(Bundle savedInstanceState)...如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
二、转换的本质 派生类可以转换为基类的本质是: ①为什么派生类可以转换为基类:派生类从基类而来,因此派生类中包含了基类的方法和成员。...此时基类可以通过指针或引用指向派生类(相当于将派生类从基类中继承的那部分方法和成员绑定到基类上了,相当于派生类被截断了),然后基类就可以将派生类假装是一个基类对象来使用(调用其中的成员/方法) ②为什么基类不能转换为派生类...如果将一个基类对象绑定到派生类的指针/引用上,此时派生类通过指针/引用访问自己新定义的成员/方法时,发现找不到(因此不能将基类转换为派生类) 例如:下面B继承于A,子类继承于父类,同时为父类的成员开辟了空间...//假设B公有继承于A A *a; B b; a = &b; //将派生类转换为基类,正确 B *p = a; //将基类再转换为派生类,错误 五、类静态类型/类动态类型 在上面我们介绍过,基类的指针或引用可以指向于基类对象也可以指向于派生类对象...演示案例② 我们修改演示案例①,上面是将基类的指针指向于派生类。
派生类与基类之间的关系: 派生类对象可以使用基类(公有的)方法。 基类指针可以在不进行显示类型转换的情况下指向派生类对象,但只能调用基类方法。...将派生类引用或指针转换为基类引用或指针称为向上强制转换,该转换使得公有继承不需要进行显示类型转换。...且该转换是可以传递的,例如基类A,其派生类AP,AP的派生类APP,则A指针或引用可以指向或引用AP类对象和APP类对象。 相反的,我们将基类指针或引用转换为派生类指针或引用称为向下强制转换。...虚函数表存储了为类对象进行声明的虚函数的地址。通常情况下,基类对象包含一个指向该类中虚函数表的指针。...因此,如果要重新定义继承的方法,则应确保与原来的原型完全相同,但是如果返回类型是基类引用或指针,则可以修改为指向派生类的引用或指针,即允许返回类型随类类型的变化而变化,这种特性被称为返回类型协变。
我们都知道C++完全兼容C语言,C语言的转换方式很简单,可以在任意类型之间转换,但这也恰恰是缺点,因为极其不安全,可能不经意间将指向const对象的指针转换成非const对象的指针,可能将基类对象指针转成了派生类对象的指针...另外,static_cast还可以将派生类指针转换为基类指针,而且一定条件下还能将基类指针转换为派生类指针,且不会报错,只是一些只有派生类才会有的函数、成员变量,转换过来的指针也不会有。...dynamic_cast,一般只用于基类和派生类之间的转换,而且只能用于派生类指针转换成基类指针,不能反向转换。...在多态中,比如上面代码中有基类Test和TestDerived,现在有一个Test指针,但不知道这个指针究竟指向的是基类还是派生类,怎么知道指针是指向的哪种对象呢?...目前c++中有3个支持RTTI的元素:dynamic_cast,将一个指向基类的指针来生成一个指向派生类的指针,否则,该运算符将返回空指针typeid,返回一个指针对象类型的值type_info,结构存储了有关特定类型的信息
类型转换成其他的SharePtr void AMyActor::MySharePtrTestCastToAnotherSharePtr() { //基类对象指向了派生类的成员.多态案例在这也是一样的...; //Const SharePtr转换成其他的SharePtr void AMyActor::MyConstSharePtrTestCastToAnotherSharePtr() { //基类对象指向了派生类的成员...TSharedPtr中的ToSharedRef()方法可以将TSharePtr转换为TShareRef 二.TShareRef 1.如何创建一个TShareRef //SharePtr如何使用 void...AsShared方法,会存着一个这个类的共享引用。...不能用派生类接 //TSharedPtr ptr22 = pOriginPtr->AsShared(); } { //正确的用法, AsShared()不能用基类接(基类指的是你继承自
/引用转换为子类对象的指针或引用(动态转换) 向上转型:子类对象指针/引用->父类指针/引用(不需要转换,赋值兼容规则) 向下转型:父类对象指针/引用->子类指针/引用(用dynamic_cast转型是安全的...static_cast,命名上理解是静态类型转换 使用场景: 用于类层次结构中基类和派生类之间指针或引用的转换 注意: 上行转换(派生类—->基类)是安全的;下行转换(基类—->派生类)由于没有动态类型检查...基类必须要有虚函数 对于下行转换,dynamic_cast是安全的(当类型不一致时,转换过来的是空指针),而static_cast是不安全的(当类型不一致时,转换过来的是错误意义的指针,可能造成踩内存...,非法访问等各种问题) const_cast,字面上理解就是去const属性 使用场景: 常量指针转换为非常量指针,并且仍然指向原来的对象 常量引用被转换为非常量引用,并且仍然指向原来的对象...使用场景: 不到万不得已,不用使用这个转换符,高危操作 使用特点: reinterpret_cast可以将整型转换为指针,也可以把指针转换为数组 reinterpret_cast可以在指针和引用里进行肆无忌惮的转换
派生类在继承函数时,如果需要覆盖(override)继承的函数,那就要在派生类中将完全相同的函数声明出来 我们可以将一个派生类对象转换为基类对象,此时派生类独有的部分将被截断,其基类部分被处理而派生类部分被忽略...我们很多时候希望的是我们通过将基类指针指向派生类,然后可以动态调用派生类的函数,这时我们可以将基类的对应函数写为虚(virtual)函数来实现,此时发生的称为动态绑定 基类通过在声明语句前加上关键字virtual...每个类都会继承其直接基类的成员,然后转换为自己的成员继续派生下去,因此最后一层派生将包含所有成员 有时候我们不希望其他类继承某个类,可以在类的声明后加上final表示无法继续派生 智能指针也支持派生到基类的类型转换...这里有一个特别的,即便处理的是基类指针,此指针指向某派生类,我们也不能隐式转换到这个派生类,如果基类中含有虚函数,我们可用用dynamic_cast强制转换 15.3 虚函数 通过对基类的指针或引用来调用虚函数时会出现动态绑定...,对于实现的内容我们一样可以使用=default简化 如果基类的析构函数不是虚函数,则delete一个指向派生类对象的基类指针将产生未定义的行为 如果定义了虚析构函数,则一样的合成移动操作将被阻止 派生类的析构函数和以往一样是空函数
当使用指针访问虚基类成员变量时,由于指针可以是指向派生类实例的基类指针,所以,编译器不能根据声明的指针类型计算偏移,而必须找到另一种间接的方法,从派生类指针计算虚基类的位置。...该变量指向一个全类共享的偏移量表,表中项目记录了对于该类 而言,“虚基类表指针”与虚基类之间的偏移量。 其它的实现方式中,有一种是在派生类中使用指针成员变量。...这些指针成员变量指向派生类的虚基类,每个虚基类一个指针。这种方式的优点是:获取虚基类地址时,所用代码比较少。然而,编译器优化代码时通常都可以采取措施避免重复计算虚基类地址。...况且,这种实现方式还有一个大弊端:从多个虚基类派生时,类实例将占用更多的内存空间;获取虚基类的虚基类的地址时,需要多次使用指针,从而效率较低等等。...MSC++的实现不是这样,MSC++有意将S::rvf编译为接受一个指向S中嵌套的R实例,而非指向S实例的指针(我们称这种行为是“给派生类的指针类型与该虚函数第一次被引入时接受的指针类型相同”)。
将A*转换为int*,使用指针直接访问 private 成员刺穿了一个类的封装性,更好的办法是让类提供 get/set 函数,间接地访问成员变量。...pa 是A*类型的指针,当 pa 指向 A 类型的对象时,向下转型失败,pa 不能转换为B*或C*类型。当 pa 指向 D 类型的对象时,向下转型成功,pa 可以转换为B*或C*类型。...从表面上看起来 dynamic_cast 确实能够向下转型,本例也很好地证明了这一点:B 和 C 都是 A 的派生类,我们成功地将 pa 从 A 类型指针转换成了 B 和 C 类型指针。...但是从本质上讲,dynamic_cast 还是只允许向上转型,因为它只会向上遍历继承链。造成这种假象的根本原因在于,派生类对象可以用任何一个基类的指针指向它,这样做始终是安全的。...本例中的情况②,pa 指向的对象是 D 类型的,pa、pb、pc 都是 D 的基类的指针,所以它们都可以指向 D 类型的对象,dynamic_cast 只是让不同的基类指针指向同一个派生类对象罢了。
1.1 RTTI的三个元素 由于只有包含虚函数的类层次结构,才能将派生类对象的地址赋给基类指针,因此RTTI只适用包含虚函数的类。...dynamic_cast运算符将使用一个指向基类的指针来生成一个指向派生类的指针,否则,该运算符返回0—空指针。 typied运算符返回一个指出对象的类型的值。...主要在以下几种场合中使用: 用于类层次结构中,基类和子类之间指针和引用的转换;当进行上行转换(把派生类的指针或引用转换成基类表示),这种转换是安全的;当进行下行转换(把基类的指针或引用转换成派生类表示)...reinterpret_cast 运算符并不会改变括号中运算对象的值,而是对该对象从位模式上进行重新解释。它主要用于将一种数据类型从一种类型转换为另一种类型。...例如,它可以将一个指针转换成一个整数,也可以将一个整数转换成一个指针,然而,其并不支持所有类型的转换,例如,可以将指针类型转换为足以存储指针表示的整形,但不能将指针转换为更小的整形或浮点型。
说明:本来基类指针是用来指向基类对象的,如果用它指向派生类对象,则进行指针类型转换,将派生类对象的指针先转换为基类的指针,所以基类指针指向的是派生类对象中的基类部分。...虚函数突破了这一限制,在派生类的基类部分中,派生类的虚函数取代了基类原来的虚函数,因此在使基类指针指向派生类对象后,调用虚函数时就调用了派生类的虚函数。...但是,从基类继承来的某些成员函数不完全适应派生类的需要,例如在例12.2中,基类的display函数只输出基类的数据,而派生类的display函数需要输出派生类的数据。...如果在派生类中没有对基类的虚函数重新定义,则派生类简单地继承其直接基类的虚函数。 定义一个指向基类对象的指针变量,并使它指向同一类族中需要调用该函数的对象。...通过该指针变量调用此虚函数,此时调用的就是指针变量指向的对象的同名函数。 通过虚函数与指向基类对象的指针变量的配合使用,就能方便地调用同一类族中不同类的同名函数,只要先用基类指针指向即可。
都能正常处理异常 异常对象的类型是由表达式的静态类型决定的,也就是我们抛出指向派生类的基类指针时,该派生类将被切去一部分 catch语句的括号内容是异常声明,类似函数的形参列表,用起来也很相近,和之前一样如果我们想要...catch捕获异常忽略掉 catch只允许最基础的转换,包括常量改变,派生向基类,数组转指针,函数转指针四种,其他的类型转换都不支持 有时候我们发现单个catch无法完全处理好异常时,我们用一个空的throw...,这都可能引起混乱 18.3 多重继承与虚继承 C++支持多重继承(很多其他语言不支持这一特性),方法就是继承列表多些几个基类,因此我们可以从多个直接基类产生派生类,这个派生类会继承所有父类的属性...要注意的是基类的构造顺序是与派生列表中基类的出现顺序一致,与派生类参数顺序无关 C11中允许派生类从多个基类中继承构造函数,但是如果多个构造函数都相同的话将产生错误,此时派生类应该自己定义一个构造函数来覆盖它们...析构函数的调用顺序与构造顺序相反的特性仍在 合成拷贝移动等操作的规则也与之前一致 我们可以用基类指针指向派生类对象,但是调用对应函数的时候编译器不会觉得不同方向的转换有好坏之分,因此当有多个接受不同基类参数但名字相同的函数时
1) 向上类型转换 将派生类指针或引用转换为基类的指针或引用被称为向上类型转换,向上类型转换会自动进行,而且向上类型转换是安全的。...2) 向下类型转换 将基类指针或引用转换为派生类指针或引用被称为向下类型转换,向下类型转换不会自动进行,因为一个基类对应几个派生类,所以向下类型转换时不知道对应哪个派生类,所以在向下类型转换时必须加动态类型识别技术...2) 多重继承的优点很明显,就是对象可以调用多个基类中的接口; 3) 如果派生类所继承的多个基类有相同的基类,而派生类对象需要调用这个祖先类的接口方法,就会容易出现二义性 4) 加上全局符确定调用哪一份拷贝...; 2) 没有任何构造函数的类派生自一个带有默认构造函数的基类,那么需要为该派生类合成一个构造函数,只有这样基类的构造函数才能被调用; 3) 带有虚函数的类,虚函数的引入需要进入虚表,指向虚表的指针...虚函数是为了实现动态编联产生的,目的是通过基类类型的指针指向不同对象时,自动调用相应的、和基类同名的函数(使用同一种调用形式,既能调用派生类又能调用基类的同名函数)。
相反,假设抛出一个数组,被抛出的对象转换为指向数组首元素的指针,相似的,假设抛出一个函数,函数转换为指向该函数的指针。...假设该指针是一个指向派生类对象的基类类型指针,则那个对象将被切割,仅仅抛出基类部分。 谨记:抛出指向局部对象的指针总是错误的,因此,在抛出指针的时候,必须确定进入处理代码时指针所指向的对象存在。...也就是说,非const对象的 throw能够与指定接受const引用的 catch匹配。 2)同意从派生类型型到基类类型的转换。...3)将数组转换为指向数组类型的指针,将函数转换为指向函数类型的适当指针。 在查找匹配catch的时候,不同意其它转换。...假设被抛出的异常对象是派生类类型的,但由接受基类类型的catch处理,那么,catch不能使用派生类特有的不论什么成员。
把精度大的类型转换为精度小的类型,static_cast使用位截断进行处理。 使用static_cast可以找回存放在void*指针中的值。...a; double * dptr = static_cast(vptr); cout<<*dptr<<endl;//输出1.999 static_cast也可以用在于基类与派生类指针或引用类型之间的转换...name;}; void OutPuttype(){cout<<_type;}; private: string _name ; string _type ; }; 此时我们进行派生类与基类类型指针的转换...int main() { //基类指针转为派生类指针,且该基类指针指向基类对象。...//基类指针转为派生类指针,且该基类指针指向派生类对象 ANIMAL * ani3 = new DOG; DOG* dog3 = static_cast(ani3);
当一个方法只有子类才有,马克-to-win:不是说基类和子类都有,开始时又是基类指针指向派生类,这时就需要downcast, see the following example. after you cast...SuperClassM_t_w() { a = 5; } public void printAsuper() { System.out.println("父类中..., default constructor. */ SuperClassM_t_w s1 = new SubClass(10); s1.printAsuper();//基类指针指向派生类时...,马克-to-win: 可以用基类指针调用基类仅有的方法, 但不能调用子类仅有的方法。...必须向下强转一下。 // s1.printA();错误 /* 我们不能去掉下面的话,因为SuperClassM_t_w没有printA方法。
最常见的使用方法就是声明基类的指针,利用该指针指向随意一个子类对象,调用对应的虚函数,能够依据指向的子类的不同而实现不同的方法。...假设没有使用虚函数的话,即没有利用C++多态性,则利用基类指针调用对应的函数的时候,将总被限制在基类函数本身,而无法调用到子类中被重写过的函数。...p->foo()和p->fuu()则是基类指针指向子类对象,正式体现多态的使用方法,p->foo()因为指针是个基类指针,指向是一个固定偏移量的函数,因此此时指向的就仅仅能是基类的foo()函数的代码了...这是一个用子类的指针去指向一个强制转换为子类地址的基类对象。结果,这两句调用的输出结果是3,2。 ...并非非常理解这样的使用方法,从原理上来解释,因为B是子类指针,尽管被赋予了基类对象地址,可是ptr->foo()在调用的时候,因为地址偏移量固定,偏移量是子类对象的偏移量,于是即使在指向了一个基类对象的情况下
但我们可以将const左值引用绑定到右值上 移动构造的具体写法类似拷贝构造,但是构造参数是自己类型的右值引用,为了完成移动构造,我们需要保证移动后源对象处于可以无害销毁的状态,源对象的指针不再指向原先的资源...重载 overload,指对一个同名方法进行了几种不同参数的实现 可以将一个派生类对象转换为基类对象,此时派生类独有的部分将被截断,其基类部分被处理而派生类部分被忽略 有时我们不希望派生类独有的部分被截断则需要使用类指针来调用重载的函数或使用指针所指的成员...我们很多时候希望的是我们通过将基类指针指向派生类,然后可以动态调用派生类的函数,这时我们可以将基类的对应函数写为虚(virtual)函数来实现,此时发生的称为动态绑定 派生类可以继承多个基类,称为多继承...每次继承一个基类就会在内存中生成一个子对象,存放了基类的成员,也正是因为这个原因派生类可以转换为基类 派生类的构造函数需要负责所有成员的初始化,尽管派生类也可以初始化继承来的基类成员,但是这不符合通常的编码思路...因此除了重载虚函数外最好不要让名称同名 派生类可以覆盖基类重载的函数,但是如果派生类希望基类重载的几个函数都在派生类中可见的话:一种方法是不覆盖任何一个重载函数或将所有重载函数都进行一次覆盖;另一种方法是为需要重载的函数名使用
这种情况未启用多态机制 如果基类中的 Swim() 是虚函数,那么运行时会根据基类引用(或指针)指向的具体对象,调用对象所属的类中的方法。...若指向派生类对象则调用派生类方法,若指向基类对象则调用基类方法。...这种情况使用了多态机制 使用基类指针或引用指向基类或派生类对象,运行时调用对象所属的类(具有继承层次关系的基类或派生类)中的方法,这就是多态。...,delete 将按派生类析构的方式来析构此指针(调用派生类析构函数和基类析构函数)。...可见使用虚继承可以解决多继承时的菱形问题,确保 在继承层次结构中,继承多个从同一个类派生而来的基类时,如果这些基类没有采用虚继承,将导致二义性。
左值引用&右值引用左值引用:常规引用,可支持取地址运算符&获取内存地址;右值引用:右值是临时对象、字面量等表达式,右值引用解决临时对象或函数返回值给左值对象时的深度拷贝;std::move:将输入的左值或右值转换为右值引用类型的临终值...oop封装C++中封装通过对类的访问权限实现,类将客观事物抽象成数据成员和方法,并通过public,protected,private三种访问权限控制其他对象对类的访问和继承。...每个虚继承的子类都有一个虚基类指针(占用一个指针的存储空间,4字节)和虚基类表(不占用类对象的存储空间)当派生类重新定义虚函数时,则将派生类的虚函数的地址添加到虚函数表中。...当一个基类指针指向一个派生类对象时,虚函数表指针指向派生类对象的虚函数表。当调用虚函数时,由于派生类对象重写了派生类对应的虚函数表项,基类在调用时会调用派生类的虚函数,从而产生多态。...虚析构函数:为了防止delete指向派生类对象的基类指针时只调用基类的析构函数引起内存泄漏using namespace std;class Base {public: virtual ~ Base
领取专属 10元无门槛券
手把手带您无忧上云