覆盖基类的函数

覆盖基类函数顾名思义就是在派生类中对基类的函数进行的重新定义。这里将会讲到下面的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++扩展了其多态性,允许将派生类对象赋给指向基类的指针。因此,可以这样编写代码:

Manmal * pManmal = new Dog;

上面的代码创建了一个新的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)的更多相关文章

  1. 走进C++程序世界------继承和派生

    继承和派生 继承是面向对象编程语言的最重要方面之一,正确的使用继承可编写出设计良好,容易于维护和扩展的应用程序.下面是在其他博客中的总结: ****************************** ...

  2. 走进C++程序世界------异常处理

    一. 概述 C++自身有着很强的纠错能力,发展到现在,已经建立了比較完好的异常处理机制. C++的异常情况无非两种,一种是语法错误.即程序中出现了错误的语句,函数.结构和类,致使编译程序无法进行.还有 ...

  3. 走进C++程序世界-----函数相关(全局变量)

    全局变量 在函数外面定义的变量的作用域为全局,在程序的任何函数中都可用.与全局变量同名的局部变量不会修改全局变量的值,但会隐藏它.如果函数中有一个与全局变量同 名的局部变量时,则在函数中使用该名称时, ...

  4. 走进C++程序世界------IO标准库介绍

    流概述    流是C++标准的组成部分,流的主要目标是,将从磁盘读取文件或将输入写入控制台屏幕的问题封装起来,创建流后程序猿就能够使用它.流将负责处理全部的细节. IO类库 在C++输入、输出操作是通 ...

  5. 走进C++程序世界-------类的定义和使用(数据成员和方法成员,析构函数,构造函数,内联实现)

    类的成员简介 在C++中,可以通过声明一个类来穿件一种新的类型.类将一组变量(他们的类型通常不同)和一组相关的函数组合在一起.类可以有各种类型的变量组成,还可以包含其他类对象.成员变量称为数据成员它们 ...

  6. 走进C++程序世界-----operator new delete 重载

     在C++ 的世界里,new 和delete 是keyword.而在C的世界里相相应的malloc和free是函数,关键C++的new和delete分析,详见前面的章节.这里就不在过多的介绍了.链接. ...

  7. 程序设计实习MOOC / 继承和派生——编程作业 第五周程序填空题1

    描述 写一个MyString 类,使得下面程序的输出结果是: 1. abcd-efgh-abcd- 2. abcd- 3. 4. abcd-efgh- 5. efgh- 6. c 7. abcd- 8 ...

  8. [C#] 走进 LINQ 的世界

    走进 LINQ 的世界 序 在此之前曾发表过三篇关于 LINQ 的随笔: 进阶:<LINQ 标准查询操作概述>(强烈推荐) 技巧:<Linq To Objects - 如何操作字符串 ...

  9. 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/ ...

随机推荐

  1. 深度观察:腾讯收购大众点评背景下的O2O大格局

    [亿欧导读] 腾讯入股大众点评获得20%股权,详情解读:①大众点评:独立自主为底线,要钱大于要流量:②腾讯:承认原生活服务O2O失败,丰富移动支付应用场景:③美团承受压力,拉手窝窝继续苦等买家:④BA ...

  2. POJ2221+模拟

    参考http://blog.sina.com.cn/s/blog_7de5c6210100tm1h.html 其实是水题............ #include<string.h> #i ...

  3. Java缓存--JCS

    添加外部包: jcs-1.3.jar concurrent-10.3.jar cache.cff # optional region "myCache" specific conf ...

  4. Ubuntu zookeeper-3.5.0-alpha启动错误 zkEnv.sh: Syntax error: "(" unexpected (expecting "fi")(转)

    昨天小猿我把Ubuntu Server64位上的 zookeeper换成了最新版本的,结果启动的时候出错:之前zookeeper-3.3.6是没有任何问题的,换成了zookeeper3.5出现了下面的 ...

  5. EventLog实现事件日志操作

    选中”我的电脑”,在其右键菜单中选择“管理”,在打开的对话框中包括了如下图所示的“日志”信息: 选中其中的某一条日志,可以看到如下的详细信息: 我们应该如何通过写代码的方式向其中添加“日志”呢? 在操 ...

  6. hdu 2089 不要62(初学数位DP)

    http://acm.hdu.edu.cn/showproblem.php?pid=2089 题意: 给定 m,.n; 求车牌号 m~n之间 有多少数字 不含 4或62     ,8652是可以的 . ...

  7. poj棋盘分割(记忆化)

    http://poj.org/problem?id=1191 黑书上P116 想了挺久 没想出来 想推出一公式来着 退不出来.. 想偏了  正解:递归 #include <iostream> ...

  8. Android 开发性能优化之SparseArray(一)

    多数Android开发者都知道在Android中可以使用HashMap来映射一种对应关系,在java开发中HashMap也算是一种很重要的数据存储结构.然后很多人在Android开发中多数都会用Has ...

  9. ArrayList源码解析

    ArrayList简介 ArrayList定义 1 public class ArrayList<E> extends AbstractList<E> implements L ...

  10. Flex 箭头(军标)库封装完成

    封装的一个月,在这个月期间还完成的一些其它的工作:公司有规定不能公布代码,我可以讲一下大致的流程,真的很抱歉! 1.用B样条曲线画箭头的两侧的曲线,这个要注意了,不要贝塞尔曲线,因为贝塞尔曲线的算法会 ...