走进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/ ...
随机推荐
- 静态分析安全测试(SAST)优缺点探析
静态分析安全测试(SAST)是指不运行被测程序本身,仅通过分析或者检查源程序的语法.结构.过程.接口等来检查程序的正确性,那么采用静分析安全测试的方法有什么优缺点呢,且让小编给你说道说道. 许多公司都 ...
- Swift 中的 Runtime
即使在 Swift APP 中没有一行 Object-c 的代码,每个 APP 也都会在 Object-c runtime 中运行,为动态任务分发和运行时对象关联开启了一个世界.更确切地说,可能在仅使 ...
- android 监听去电实现ip拨号 广播接收者
利用广播实现ip拨号 布局文件: <?xml version="1.0" encoding="utf-8"?> <LinearLayout x ...
- ASP.NET MVC 入门2、项目的目录结构与核心的DLL
我们新建一个ASP.NET MVC的Web Application后,默认的情况下,项目的目录结构如下: App_Data :这个目录跟我们一般的ASP.NET website是一样的,用于存放数据. ...
- easyui源码翻译1.32--Window(窗口)
前言 扩展自$.fn.panel.defaults.使用$.fn.window.defaults重写默认值对象.下载该插件翻译源码 窗口控件是一个浮动和可拖拽的面板可以用作应用程序窗口.默认情况下,窗 ...
- 133. Clone Graph
题目: Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. ...
- RxJava开发精要3-向响应式世界问好
原文出自<RxJava Essentials> 原文作者 : Ivan Morgillo 译文出自 : 开发技术前线 www.devtf.cn 转载声明: 本译文已授权开发者头条享有独家转 ...
- Android 设置按钮为透明
设置一个按钮为透明, (1)修改配置文件 <Button android:id="@+id/btnAppMore" android:layout_width="wr ...
- ActionBar官方教程(2)选主题让应用支或不支持ActionBar及支持ActionBar的应用如何隐藏和显示
Adding the Action Bar As mentioned above, this guide focuses on how to use the ActionBar APIs in the ...
- 【DataStructure In Python】Python模拟栈和队列
用Python模拟栈和队列主要是利用List,当然也可以使用collection的deque.以下内容为栈: #! /usr/bin/env python # DataStructure Stack ...