走进C++程序世界-----继承和派生(2)
覆盖基类的函数
覆盖基类函数顾名思义就是在派生类中对基类的函数进行的重新定义。这里将会讲到下面的2个知识点:
1、隐藏基类的方法
2、调用基类的方法(隐式和显示调用基类的方法)
/*
*derive2.cpp
*Date : 2013-9-24
*Author: sjin
*Mail:413977243@qq.com
*/
#include <iostream>
#define N 0 using namespace std; /*知识点:
* 1、隐藏基类的方法(就是在派生类中重新实现函数的定义)
* 2、当基类的方法被覆盖时,仍可通过限定方法名来调用它,如下格式:
* baseclass::Method();
*/ /*基类*/
class Manmal{
public:
//Manmal():itsAge(2),itsWeight(5){ cout << " create Manmal object..."<<endl;}
//~Manmal(){cout << " destroy Manmal object..."<<endl;} void Move() const { cout << "Manmal move one step..." << endl;}
void Move(int distance) const
{
cout << "Manmal Move '" << distance << "' steps..." << endl;
} private:
int itsAge;
int itsWeight;
}; /*派生类*/
class Dog : public Manmal {
public:
//Dog() {cout << " create Dog object..." << endl;}
//~Dog() {cout << " destroy Dog object..."<< endl;} /*隐藏了基类的Move()方法*/
void Move() const
{
cout << "Dog move 5 steps..." << endl;
cout << "隐式调用基类方法(start):" << endl;
Manmal::Move();
Manmal::Move(1000);
cout << "隐式调用基类方法(end):" << endl;
} }; int main()
{
Manmal bigAnimal;
Dog Fido;
cout << "**********Manmal bigAnimal*************" << endl;
bigAnimal.Move();
bigAnimal.Move(2);
cout << "**********Dog Fido*************" << endl;
Fido.Move();
//Fido.Move(2);
/* 上面将会出现下面的错误
* derive2.cpp:56: error: no matching function for call to ‘Dog::Move(int)’
* derive2.cpp:43: note: candidates are: void Dog::Move() const
* 也就是说: 覆盖任一个重载的方法后,该方法的其他所有版本都会被隐藏。
* 如果补希望他们被隐藏,必须对其进行覆盖。
*/ /*显式调用被隐藏基类的方法*/
cout << "显式调用基类方法(start):" << endl;
Fido.Manmal::Move();
Fido.Manmal::Move(200);
cout << "显式调用基类方法(end):" << endl; }
输出如下:
**********Manmal bigAnimal*************
Manmal move one step...
Manmal Move '2' steps...
**********Dog Fido*************
Dog move 5 steps...
隐式调用基类方法(start):
Manmal move one step...
Manmal Move '1000' steps...
隐式调用基类方法(end):
显式调用基类方法(start):
Manmal move one step...
Manmal Move '200' steps...
显式调用基类方法(end):
虚方法
DOG对象是一个Manmal对象,因此这就意味着Dog对象继承了基类的属性和功能。C++扩展了其多态性,允许将派生类对象赋给指向基类的指针。因此,可以这样编写代码:
上面的代码创建了一个新的Dog对象,并返回了一个指向该对象的指针,然后将该指针赋给一个Manmal指针。之所以可以这样做,是因为狗也是一种动物。如果希望在调用被Dog覆盖的方法是,将调用正确的函数,虚函数让你能够做到这一点,要创建虚函数,在函数声明前加上关键字Virtual。看下面的代码:
/*
*virtual.cpp
*Date : 2013-9-20
*Author: sjin
*Mail:413977243@qq.com
*/
#include <iostream>
using namespace std; /*知识点:
* 1、如何创建虚函数?
* 在函数声明前加上virtual 关键字
* 2、使用虚方法的意义
* 基类中如果声明了虚方法,说明它的派生类中有可能会覆盖这个方法。
* 3、如果在基类中将一个成员方法标记为虚方法,还需要在派生类中将它标记为虚方法吗?
* 不需要,方法被声明为虚方法后,如果在派生类覆盖它,它仍是虚方法。在派生类继续
* 将其标记为虚方法是个不错的主意,但是没有必要这么作,这样使代码更容易理解。
* */ class Manmal {
public:
Manmal():itsAge() { cout << "Manmal constrctor...\n";}
virtual ~Manmal() { cout << "Manmal destructor...\n";}
void Move() const { cout << "Manmal move one step\n";}
virtual void Speak() const { cout << "Manmal speak!\n";} protected:
int itsAge;
}; class Dog :public Manmal{
public:
Dog() { cout << " Dog constrctor...\n";}
virtual ~Dog() { cout << " Dog destructor..\n";}
void WagTail() { cout << " Wagging Tail...\n";}
void Speak() const { cout << "Dog woof!\n";}
void Move() const { cout << "Dog moves 5 steps ...\n";}
}; int main()
{
/*创建一个信的dog对象,并返回该对象的指针,然后将该指针付给一个
* Manmal指针。
* 这是多态的本质,例如:可创建很多类型的窗口,包括对话框,可滚动
* 窗库和列表框,然后给每种窗口定义一个虚方法draw().通过创建一个窗口指针,
* 并将对话框和其他的派生对象赋給指针,就可以通过调用draw(),而不用考虑运行
* 时指针只想的实际对象类型,程序将调用正确的draw()方法。
* */ Manmal *pDog = new Dog;
pDog->Move();
pDog->Speak();/*虚方法,被覆盖*/
/*释放对象*/
delete pDog;
return 0;
}
输出:
Manmal constrctor...
Dog constrctor...
Manmal move one step
Dog woof!
Dog destructor..
Manmal destructor...
从上面的输出可以看到,Manmal 指针pDog ,调用了Dog类的SPEAK()方法,这里很神奇!但是Move()函数调用的仍然是manmal类的方法。
走进C++程序世界-----继承和派生(2)的更多相关文章
- 走进C++程序世界------继承和派生
继承和派生 继承是面向对象编程语言的最重要方面之一,正确的使用继承可编写出设计良好,容易于维护和扩展的应用程序.下面是在其他博客中的总结: ****************************** ...
- 走进C++程序世界------异常处理
一. 概述 C++自身有着很强的纠错能力,发展到现在,已经建立了比較完好的异常处理机制. C++的异常情况无非两种,一种是语法错误.即程序中出现了错误的语句,函数.结构和类,致使编译程序无法进行.还有 ...
- 走进C++程序世界-----函数相关(全局变量)
全局变量 在函数外面定义的变量的作用域为全局,在程序的任何函数中都可用.与全局变量同名的局部变量不会修改全局变量的值,但会隐藏它.如果函数中有一个与全局变量同 名的局部变量时,则在函数中使用该名称时, ...
- 走进C++程序世界------IO标准库介绍
流概述 流是C++标准的组成部分,流的主要目标是,将从磁盘读取文件或将输入写入控制台屏幕的问题封装起来,创建流后程序猿就能够使用它.流将负责处理全部的细节. IO类库 在C++输入、输出操作是通 ...
- 走进C++程序世界-------类的定义和使用(数据成员和方法成员,析构函数,构造函数,内联实现)
类的成员简介 在C++中,可以通过声明一个类来穿件一种新的类型.类将一组变量(他们的类型通常不同)和一组相关的函数组合在一起.类可以有各种类型的变量组成,还可以包含其他类对象.成员变量称为数据成员它们 ...
- 走进C++程序世界-----operator new delete 重载
在C++ 的世界里,new 和delete 是keyword.而在C的世界里相相应的malloc和free是函数,关键C++的new和delete分析,详见前面的章节.这里就不在过多的介绍了.链接. ...
- 程序设计实习MOOC / 继承和派生——编程作业 第五周程序填空题1
描述 写一个MyString 类,使得下面程序的输出结果是: 1. abcd-efgh-abcd- 2. abcd- 3. 4. abcd-efgh- 5. efgh- 6. c 7. abcd- 8 ...
- [C#] 走进 LINQ 的世界
走进 LINQ 的世界 序 在此之前曾发表过三篇关于 LINQ 的随笔: 进阶:<LINQ 标准查询操作概述>(强烈推荐) 技巧:<Linq To Objects - 如何操作字符串 ...
- C#7.2——编写安全高效的C#代码 c# 中模拟一个模式匹配及匹配值抽取 走进 LINQ 的世界 移除Excel工作表密码保护小工具含C#源代码 腾讯QQ会员中心g_tk32算法【C#版】
C#7.2——编写安全高效的C#代码 2018-11-07 18:59 by 沉睡的木木夕, 123 阅读, 0 评论, 收藏, 编辑 原文地址:https://docs.microsoft.com/ ...
随机推荐
- .NET事件的指导原则
C#允许编写所需的各种类型的事件.但是,为了与.NET Framwork的组件相兼容,开发人员必须遵循微软为此建立的一系列指导原则.这些指导原则的核心是,事件处理程序必须拥有两个参数.第一个参数是一个 ...
- USB Type-C接口完美无瑕?小心这五点
今年下半年发布的新手机中,采用USB Type-C接口与传统micro USB接口的手机,所占比例大概是一半对一半.采用Type-C接口的手机大多数都是国产手机,而像三星.摩托罗拉以及索尼等老牌的手机 ...
- Qt刷新机制的一些总结(Qt内部画的时候是相当于画在后台一个对象里,然后在刷新的时候调用bitblt统一画,调用window的api并不会影响到后面的那个对象)
前段时间做过一个界面刷新的优化,遇到的坑比较多,在这里做一点点总结吧. 优化的方案是滚动滚动条的时候用截屏的方式代替界面全部刷新,优化完成后,界面在滚动时效率能提升大概一倍,背景介绍完毕. ...
- webstrom使用记录
很不方便的一点: 输入 $("#div p" 之后输入",就会变成$("#div p""" 这样,很不爽.
- addlinkedserver
http://blog.sina.com.cn/s/blog_5321db9d0100f89g.html --创建链接服务器 exec sp_addlinkedserver 'ITSV ', ' ' ...
- WIKIOI 1222信与信封问题
题目描述 Description John先生晚上写了n封信,并相应地写了n个信封将信装好,准备寄出.但是,第二天John的儿子Small John将这n封信都拿出了信封.不幸的是,Small Joh ...
- easyui datagriad 框架 自适应r
easyui datagriad 框架 在做列自适应时可以采取以下步骤: 1. fitColumns: true,/*自动扩大或缩小列的尺寸以适应表格的宽度并且防止水平滚动*/ 使之保持与父类宽度相同 ...
- 【转】G++ 处理 /usr/bin/ld: cannot find -lc
原文网址:http://blog.sina.com.cn/s/blog_67bbb71101010tto.html 用g++编译C++程序时显示出:/usr/lib/ld: cannot find - ...
- ArrayList源码解析
ArrayList简介 ArrayList定义 1 public class ArrayList<E> extends AbstractList<E> implements L ...
- Tomcat工作原理详解
一.Tomcat背景 自从JSP发布之后,推出了各式各样的JSP引擎.Apache Group在完成GNUJSP1.0的开发以后,开始考虑在SUN的JSWDK基础上开发一个可以直接提供Web服务的JS ...