如何打造具有吸引力的服装鞋帽网站建设并有效进行营销?
摘要:服装鞋帽 网站建设,营销型网站建设明细报,记事本做网站怎么不行啦,怎样买空间做网站C基础讲解第六期 代码中也有对应知识注释,别忘看,一起学习! 一、多
服装鞋帽 网站建设,营销型网站建设明细报,记事本做网站怎么不行啦,怎样买空间做网站C基础讲解第六期 代码中也有对应知识注释#xff0c;别忘看#xff0c;一起学习#xff01; 一、多态1. 问题引出2. 多态的概念和使用3. 多态的原理4. 虚析构函数5. 动态类型识别(dynamic_cast)(1) 自定义类型(2). dynamic_cast(3). typeid 6. 纯虚函数 纯虚函数需要补充 一… C基础讲解第六期 代码中也有对应知识注释别忘看一起学习 一、多态1. 问题引出2. 多态的概念和使用3. 多态的原理4. 虚析构函数5. 动态类型识别(dynamic_cast)(1) 自定义类型(2). dynamic_cast(3). typeid 6. 纯虚函数 纯虚函数需要补充 一、多态
1. 问题引出
#includeiostream
using namespace std;class Parent
{public:void show(){coutthis is parentendl;}
};class Child : public Parent
{public:void show(){coutthis is childendl;}
};int main()
{Child c;Parent p;p c; //向上转型 大的赋给小的Parent *p1 new Child; //基类指针指向派生类对象p1-show(); //会调用基类的show是静态联编编译器会根据p1的类型(Parent*)调用Parent类中的show函数return 0;
}2. 多态的概念和使用 在基类指针指向基类对象的时候就使用基类中的方法和属性 在指向派生类对象的时候就使用派生类中的方法和属性 通俗的说基类指针可以按照基类的方法来做事也可以按照派生类的方法来做事它有多种形态或者说多种表现方式。 我们将这种现象称为多态。 多态产生的条件: 要有继承要有虚函数重写(发生在不同作用域中,函数原型相同), 派生类中的重写函数前面加不加virtual都可以基类指针指向派生类对象 #includeiostream
using namespace std;class Parent
{public:virtual void show() //被virtual修饰的函数叫虚函数{coutthis is parentendl;}
};class Child : public Parent //1.要有继承
{public:void show() //2.要有虚函数重写发生在不同作用域中函数原型相同派生类中的重写函数前面加不加virtual都可以{coutthis is childendl;}
};int main()
{Parent *p1 new Child; //3.基类指针指向派生类对象p1-show(); //动态联编运行的时候才知道p1指向什么对象delete p1;p1 nullptr;p1 new Parent; //基类指针指向基类对象调用的是基类中的方法p1-show(); //相同的语句有不同的执行结果(多态)return 0;
}
result:
this is child
this is parent总结: 其实多态的作用就是,派生类重写基类中的虚函数, 这样当我们基类指针指向什么类型,那么调用的方法就是指向类型的类中的方法和属性 记住向上转型,只允许基类指针指向派生类对象,基类引用可以引用派生类对象。派生类指针不能指向基类对象, 派生类引用也不能引用基类对象 3. 多态的原理 根据上一期所讲,当我们算大小的时候,存在虚函数表指针,其会占8个字节 所以看到结果不要傻眼 #includeiostream
using namespace std;class Parent
{public:int a;virtual void show() //被virtual修饰的函数叫虚函数{coutthis is parentendl;}
};class Child : public Parent //1.要有继承
{public:void show() //2.要有虚函数重写发生在不同作用域中函数原型相同{coutthis is childendl;}
};int main()
{Parent p;Child c;coutsizeof(p)endl;coutsizeof(c)endl;coutparent对象的地址pendl;coutparent成员变量a的起始地址p.aendl;
}result:
16
16
parent对象的地址0x7fff57881350
parent成员对象的起始地址0x7fff578813584. 虚析构函数 根据析构的规则,只能从当前基类开始往上调用析构函数,而并不能调用派生类中的析构函数. 通过将基类中的析构函数设置为虚析构函数,可以通过delete正确的调用析构函数. 也就是我基类指针指向哪个类型, 就先调用那个类中的析构函数 虚析构函数通过基类指针释放派生类对象 #includeiostream
using namespace std;class Parent
{public:int a;virtual void show() //被virtual修饰的函数叫虚函数{coutthis is parentendl;}virtual ~Parent(){coutparent 的析构函数endl;}
};class Child : public Parent //1.要有继承
{public:void show() //2.要有虚函数重写发生在不同作用域中函数原型相同{coutthis is childendl;}~Child(){cout child 的析构函数endl;}
};int main()
{Parent *p1 new Child;p1-show();delete p1; //释放派生类对象, 虚析构函数通过基类指针释放派生类对象p1 nullptr;return 0;
}基类中析构函数不加virtual:
this is child
parent 的析构函数基类中析构函数加上virtual:
this is child
child 的析构函数
parent 的析构函数5. 动态类型识别(dynamic_cast) 新的关键词: dynamic_cast dynamic_cast是c中新关键词dynamic_cast用于基类和派生类之间的类型转换dynamic_cast要求使用的目标类型是多态的 既要求所在类至少有一个虚函数 用于指针转换时,转换失败返回nullptr 用于引用转换时,转换失败引发bad_cast异常(异常处理失败,后期会讲) 优势: 不用显示的声明和定义虚函数不用为类族中的每个类分配类型ID 缺点: 只能用于有虚函数的类 (1) 自定义类型 手动去封装一个函数去实现什么情况可以转换类型,什么情况下不能转发,防止编译器报错 #includeiostream
using namespace std;class Parent
{private:int a;public:enum{ID 0};virtual int GetID(){return ID;}
};class Child : public Parent
{public:int array[102400];int a;enum{ID 1};int GetID(){return ID;}
};void fun(Parent *p)
{//Child *c (Child *)p; //使用强转类型派生类指针指向基类对象if(p-GetID() Child::ID) //如果成立说明指向派生类对象{Child* c (Child*)p;c-array[102400 - 1] 100;cout 转换成功endl;}else{cout 不能转换 endl;}
}int main()
{Parent *p new Child; //基类指针指向派生类对象,调用的方法是派生类中的方法多态fun(p);Parent *p1 new Parent; //基类指针指向基类对象调用的方法是基类中的方法多态fun(p1);return 0;
}result:
转换成功
不能转换(2). dynamic_cast 总结: dynamic_cast很优雅, 不像强转类型会造成系统崩溃, 其会去检查是否可以转换类型. 并且不需要我们向上面一样手动去封装一个判断能否转换类型的函数 #includeiostream
using namespace std;class Parent
{private:int a;public:virtual void show(){}
};class Child : public Parent
{public:int array[102400];void show(){}
};void fun(Parent *p)
{//Child *c (Child *)p; //使用强转类型派生类指针指向基类对象Child *c dynamic_castChild*(p); //如果p指向的是基类对象则转换失败转换失败返回nullptrif(nullptr c){cout转换失败endl;}else{c-array[102400 - 1] 100;cout转换成功endl;}
}int main()
{Parent *p new Child; //当我们基类指针指向派生类对象在fun中进行强转时是没有问题的fun(p);Parent *p1 new Parent;fun(p1);return 0;
}
result:
转换成功
转换失败(3). typeid typeid运算符用来获取一个表达式的类型信息 typeid的操作对象可以是表达式,也可以是数据类型,使用方法如下: typeid(data Type);typeid(expression); 总结: typeid关键词返回对应参数的类型信息typeid关键词返回一个type_info类对象当typeid参数为NULL时,抛出一个bad_cast异常使用type_info类需要包含typeinfo头文件 #includeiostream
#includetypeinfo
using namespace std;class Parent
{private:int a;public:virtual void show(){}
};class Child : public Parent
{public:int array[102400];void show(){}
};void fun(Parent* p)
{if(typeid(*p) typeid(Child)){Child* c (Child*)p;c-array[102400 - 1] 100;cout 转换成功endl;}else if(typeid(*p) typeid(Parent)){cout不能转换endl;}
}int main()
{int a;char ch;Parent p1;Child c1;const type_info pa typeid(a); const type_info pb typeid(ch);const type_info pc typeid(p1);const type_info pd typeid(c1);cout pa.name() endl;cout pb.name() endl;cout pc.name() endl;cout pd.name() endl;Parent *p new Child;fun(p);Parent* p2 new Parent;fun(p2);result:
i
c
6Parent
5Child
转换成功
不能转换
}6. 纯虚函数 在c中,可以将函数声明为纯虚函数,语法格式 virtual 返回值类型 函数名 (函数参数) 0; 含有纯虚函数的类为抽象类,不能实例化 基类中的纯虚函数不需要实现 并且继承它的派生类必须实现基类的纯虚函数 #includeiostream
#includetypeinfo
using namespace std;class Parent //含有纯虚函数的类称为抽象类不能实例化
{private:int a;public:virtual void print() 0; //纯虚函数没有函数体
};class Child : public Parent
{public:void print(){coutthis is childendl;}
};int main()
{//Parent p; // p.print();Parent *p new Child; //可以创建子类对象基类为抽象类不能实例化对象p-print();}纯虚函数需要补充
