C++继承的学习笔记

1、在继承中,private类型不能被继承。

公有继承,基类中的public在派生类中还是public类型,protected类型还是protected类型。

保护继承,基类中的public,protected在派生类中均为protected类型。

私有继承,基类中的public,protected均为private类型。

2、当定义一个类对象时,首先从顶层依次调用基类的构造函数,最后调用自身的构造函数。

析构函数的调用顺序与构造函数正好相反,首先调用自身的析构函数,然后依次调用基类的析构函数。

3、子类与父类中函数如果有重名,如果子类中隐藏了父类的方法,那么父类中同名的方法(重载方法)都将被隐藏。

4、在多继承中,当多个基类中有相同的函数名时,需要明确指明调用的是哪一个基类。

5、在多继承中,如果cbird类和cfish类均是canimal的子类,那么当从cbird和cfish中派生出cwaterbird时,将存在两个canimal的拷贝,虚继承将使得子类中只存在一个基类。

6、类型转换是指将某一个类型的对象转换为另一个类型的对象。在应用程序中,对象的类型转换主要是指子类和父类之间的转换。因此这种转换主要有两种形式,向上类型转换和向下类型转换。向上类型转换是指从子类到父类的转换,这种转换是安全的,因为子类具有父类中被外界能够访问的方法。

向下类型转换是从父类到子类的转换,这种类型类型转换是不安全的。因为通常在子类中提供了父类不具有的方法,将父类转换为子类后,试图调用这些实际不存在的方法,必然会出现错误。

向上类型转换是比较安全的,编译器允许直接将子类对象赋值给基类对象。

如下代码:

#include<iostream>
#include<string>
#include<cstring>
using namespace std;
class cemployee
{
protected:
	int m_nid;
    string m_szname;
	string m_szdepart;
public:
	cemployee()
	{
        m_szname="han";

		cout << "employee 构造函数被调用 " << endl;
	}

   virtual void outputname()
	{
		cout << "基函数员工姓名:" << m_szname << endl;
	}
};

class coperator:public cemployee
{
private:
    string m_szpassword;
public:
	coperator()
	{
	    m_szpassword = "123";
		cout << "coperator 构造函数被调用" << endl;
	}

	void outputname()
	{
		cout << "派生类员工姓名:" << m_szname << endl;
	}
};
int main()
{

	coperator * poperator = new coperator();
	cemployee *pemp = poperator;
	pemp->outputname();
//	delete poperator();
	pemp = NULL;

	return 0;
}

cemployee *pemp = poperator;语句直接将子类对象指针直接赋值给基类指针,这是完全合法的。语句pemp->outputname();将调用outputname()方法,如果outputname()是虚函数则调用子类的,否则执行基类的outputname()方法。

向下类型转换。是一种不安全的类型转换,因此编译器不允许直接通过赋值的方式将基类对象赋值给子类的对象。

如下主函数,编译器无法通过。

int main()
{

	cemployee * pemp = new cemployee();
	coperator *poperator = pemp;
	poperator->outputname();
//	delete poperator();
//	pemp = NULL;

	return 0;
}

如果非要实现,可以采用强制转换。改为如下:

int main()
{

	cemployee * pemp = new cemployee();
	coperator *poperator = (coperator*)pemp;
	poperator->outputname();
//	delete poperator();
//	pemp = NULL;

	return 0;
}

上述转换是非常不安全的,如果我们使用poperator 对象调用coperator类特有的方法,例如login()方法。

还有一种可以利用dynamic_cast进行动态转换。利用它可以实现两个比较安全的转换。如果待转换的对象类型与目标类型不相同,则转换将会失败。可以通过转换的结构来判断是否成功。

主函数:

int main()
{

    cemployee * pemp = new coperator();
	coperator *poperator = dynamic_cast<coperator*>(pemp);
	if(poperator != NULL)
	{
		cout << "转换成功" << endl;
	}
	else
		cout << "转换失败" << endl;
	delete pemp;
	poperator = NULL;
        return 0;
}
/*在上述代码中,定义一个父类的指针对象pemp,并用子类的构造函数进行构建。这样,实际上是pemp是一个子类对象。语句“coperator * poperator=<coperator*>(pemp)”将cemployee类型转换为coperator类型对象。如果使用cemployee函数构建,类型转换将会失败。因为源对象pemp构建的类型与目标对象poperator的类型不一致。*/

dynamic_cast有一个缺陷,就是待转换的源对象必须有具有虚拟方法表,即源对象中必须有虚拟方法。可以将析构函数声明为虚析构函数就可以轻松解决这个缺陷。

时间: 2024-11-12 17:59:30

C++继承的学习笔记的相关文章

c++代码重用—私有继承(学习笔记)

继承的准则 派生类不继承基类的接口 >因为基类的公有方法成为派生类的私有方法 派生类会继承实现 student类示例 1.私有继承的声明 1 class student:private std::string,private std::valarray < double > 2 { 3 public: 4 .... 5 }; 需要注意的问题: private是默认值,如果这里省略,也会导致私有继承 使用多个基类的继承也被称为multiple inheritance在下一节中了解 最重要的

C++中class(类)与继承白话学习笔记

1.class(类) class Drink{//定义饮料类 public://public下面的东西可以被外面访问 char* type;//饮料种类 double price;//饮料价格 double volume;//饮料体积 double currentVolume;//饮料剩余体积 bool isEmpty();//判是否喝完:成员函数(member function) void addDrink(double vol);//添加饮料:成员函数 Drink();//初始化函数,用于初

JavaScript 学习笔记 - 对象和继承

本文是JavaScript The Good Part 有关对象和继承的学习笔记. 1. Object.create 本函数是ECMAScript 5中的标准函数,其作用是用一个对象作为原型来生成另一个对象,可以用以下的code 模拟实现. if(typeof Object.create !== 'function') { Object.create = function(proto){ var F = function(){}; if(typeof proto !== 'object'){ /

C++学习笔记之继承

一.基类和派生类 很多时候,一个类的对象也“是”另一个类的对象,如矩形是四边形,在C++中,矩形类Rectangle可以由四边形类Quad继承而来,于是,四边形类Quad是基类,矩形类Rectangle是派生类.但是如果说四边形一定是矩形显然不对.几个简单的基类和派生类的例子: 基类                         派生类   食物 米饭.面条.水饺   交通工具 汽车.火车.飞机 国家 中国.美国.西班牙 可以看出,每个派生类的对象都是基类的一个对象,并且一个基类可以有很多派生

Java学习笔记之继承

一.继承的基础 在Java术语中,被继承的类叫超类(superclass),继承超类的类叫子类(subclass). 举例说明: 1 class Box 2 { 3 public double width; 4 public double height; 5 public double depth; 6 7 //重载构造方法 8 public Box(Box ob) 9 { 10 width = ob.width; 11 height = ob.height; 12 depth = ob.dep

C++ Primer 学习笔记_72_面向对象编程 --句柄类与继承[续]

面向对象编程 --句柄类与继承[续] 三.句柄的使用 使用Sales_item对象能够更easy地编写书店应用程序.代码将不必管理Item_base对象的指针,但仍然能够获得通过Sales_item对象进行的调用的虚行为. 1.比較两个Sales_item对象 在编写函数计算销售总数之前,须要定义比較Sales_item对象的方法.要用Sales_item作为关联容器的keyword,必须能够比較它们.关联容器默认使用keyword类型的小于操作符,可是假设给Sales_item定义小于操作符,

C++ Primer 学习笔记_67_面向对象编程 --转换与继承、复制控制与继承

面向对象编程 --转换与继承.复制控制与继承 I.转换与继承 引言: 由于每一个派生类对象都包括一个基类部分,因此能够像使用基类对象一样在派生类对象上执行操作. 对于指针/引用,能够将派生类对象的指针/引用转换为基类子对象的指针/引用. 基类类型对象既能够作为独立对象存在,也能够作为派生类对象的一部分而存在,因此,一个基类对象可能是也可能不是一个派生类对象的部分,因此,没有从基类引用(或基类指针)到派生类引用(或派生类指针)的(自己主动)转换. 关于对象类型,尽管一般能够使用派生类型的对象对基类

C++ Primer 学习笔记_95_用于大型程序的工具 --多重继承与虚继承

用于大型程序的工具 --多重继承与虚继承 引言: 大多数应用程序使用单个基类的公用继承,但是,在某些情况下,单继承是不够用的,因为可能无法为问题域建模,或者会对模型带来不必要的复杂性. 在这些情况下,多重继承可以更直接地为应用程序建模.多重继承是从多于一个直接基类派生类的能力,多重继承的派生类继承其所有父类的属性. 一.多重继承 1.定义多个类 为了支持多重继承,扩充派生列表: class Bear : public ZooAnimal { //... }; 以支持由逗号分隔的基类列表: cla

C++ Primer 学习笔记_96_用于大型程序的工具 --多重继承与虚继承[续1]

用于大型程序的工具 --多重继承与虚继承[续1] 四.多重继承下的类作用域 成员函数中使用的名字和查找首先在函数本身进行,如果不能在本地找到名字,就继续在本类中查找,然后依次查找每个基类.在多重继承下,查找同时检察所有的基类继承子树 -- 在我们的例子中,并行查找 Endangered子树和Bear/ZooAnimal子树.如果在多个子树中找到该名字,则那个名字的使用必须显式指定使用哪个基类;否则,该名字的使用是二义性的. [小心地雷] 当一个类有多个基类的时候,通过对所有直接基类同时进行名字查