8.5 C++ 继承与多态
C/C++语言是一种通用的编程语言,具有高效、灵活和可移植等特点。C语言主要用于系统编程,如操作系统、编译器、数据库等;C语言是C语言的扩展,增加了面向对象编程的特性,适用于大型软件系统、图形用户界面、嵌入式系统等。C/C++语言具有很高的效率和控制能力,但也需要开发人员自行管理内存等底层资源,对于初学者来说可能会有一定的难度。
继承的基本语法: 继承的目的就是用于提高代码的复用性,减少重复代码的开发,提高工作效率,先来定义简单的继承关系.
#include <iostream>
using namespace std;
class BasePage
{
private:
int m_x;
protected:
int m_y;
public:
void header() { cout << "header" << endl; }
void footer() { cout << "footer" << endl; }
};
// 新建一个News类,以公有属性继承BasePage类中的内容
class News :public BasePage
{
public:
void connect() { cout << "connect" << endl; }
};
int main(int argc, char *argv[])
{
News news;
news.header();
news.footer();
system("pause");
return 0;
}
继承中的构造/析构函数: 继承后的构造顺序base start -> news start析构顺序news end -> base end.
#include <iostream>
using namespace std;
class BasePage
{
public:
BasePage(){ cout << "base page -> start" << endl; }
~BasePage(){ cout << "base page -> end" << endl; }
};
class News :public BasePage
{
public:
News(){ cout << "news page -> start" << endl; }
~News(){ cout << "news page -> end" << endl; }
};
void call()
{ // 此处如果初始化写在main中,将无法看到析构函数的执行
News news;
}
int main(int argc, char *argv[])
{
call();
system("pause");
return 0;
}
继承下的同名函数调用: 在继承多个类的时候,难免会出现同名函数的冲突问题,在调用是可以指明其作用域.
#include <iostream>
using namespace std;
class BasePage
{
public:
void func(int x, int y)
{
cout << "BasePage -> " << x + y << endl;
}
};
class News :public BasePage
{
public:
void func(int x, int y)
{
cout << "News -> " << x + y << endl;
}
};
int main(int argc, char *argv[])
{
News news;
// 如果想调用父类的func()则需要
news.BasePage::func(10,20);
// 调用子类的则是
news.func(100, 200);
system("pause");
return 0;
}
继承下的静态成员属性: 静态成员属性也可以直接通过作用域方式直接调用.
#include <iostream>
using namespace std;
class BasePage
{
public:
static int m_x;
public:
static void func(int x, int y) {cout << "BasePage -> " << x + y << endl;}
};
class News :public BasePage
{
public:
static int m_x;
public:
static void func(int x, int y) {cout << "News -> " << x + y << endl;}
};
int BasePage::m_x = 100;
int News::m_x = 200;
int main(int argc, char *argv[])
{
News news;
cout << News::m_x << endl;
cout << News::BasePage::m_x << endl;
News::func(10,20);
News::BasePage::func(100,200);
system("pause");
return 0;
}
多继承的调用: 定义Super派生类,分别继承Base1和Base2这两个基类.
#include <iostream>
using namespace std;
class Base1
{
public:
int m_x;
public:
Base1(){ m_x = 10; }
void show() { cout << m_x << endl; }
};
class Base2
{
public:
int m_x;
public:
Base2(){ m_x = 20; }
void show() { cout << m_x << endl; }
};
class Super :public Base1, public Base2
{
public:
int m_y;
public:
Super(){ m_y = 30; }
void display(){ cout << m_y << endl; }
};
int main(int argc, char *argv[])
{
Super super;
cout << super.Base1::m_x << endl;
cout << super.Base2::m_x << endl;
cout << super.m_y << endl;
super.Base1::show();
super.display();
system("pause");
return 0;
}
菱形继承(虚继承): 虚继承可能会出现多个基类中存在相同的成员数据,从而造成内存开销过大,虚基类即可解决开销问题.
#include <iostream>
using namespace std;
class Animal
{
public:
int m_Age;
};
// 虚基类 Sheep
class Sheep :virtual public Animal { };
// 虚基类 Tuo
class Tuo :virtual public Animal { };
// 定义派生类
class SheepTuo :public Sheep, public Tuo { };
int main(int argc, char *argv[])
{
SheepTuo ptr;
ptr.Sheep::m_Age = 10;
ptr.Tuo::m_Age = 20;
cout << ptr.Sheep::m_Age << endl;
cout << ptr.Tuo::m_Age << endl;
cout << ptr.m_Age << endl;
system("pause");
return 0;
}
虚函数实现动态多态: 动态多态的作用是,通过传递不同的类指针,实现调用不同的方法,同一个结构返回不同的状态.
#include<iostream>
using namespace std;
class Animal
{
public:
virtual void speak() { cout << "Animal speak" << endl; }
virtual void eat() { cout << "Animal eat" << endl; }
};
class Cat :public Animal
{
public:
void speak() { cout << "Cat speak" << endl; }
virtual void eat() { cout << "cat eat" << endl; }
};
class Dog :public Animal
{
public:
void speak() { cout << "Dog speak" << endl; }
virtual void eat() { cout << "dog eat" << endl; }
};
void doSpeak(Animal & animal)
{
animal.speak();
}
int main(int argc, char *argv[])
{
Cat cat_ptr;
doSpeak(cat_ptr); // 调用同一个函数,返回不同的结果
Dog dog_ptr;
doSpeak(dog_ptr);
system("pause");
return 0;
}
纯虚函数实现多态: 如果父类中存在纯虚函数,子类继承父类后就必须要实现纯虚函数,父类中存在纯虚函数,该类无法实例化对象,只能被继承后实现,这种类也被叫做抽象类.
#include <iostream>
using namespace std;
class AbstractCalculator
{
public:
int x;
int y;
public:
// virtual int getResult() { return 0; }; // 定义虚函数
virtual int getResult() = 0; // 定义纯虚函数
void Set_Val(int x, int y){ this->x = x; this->y = y; };
};
class AddCalculator :public AbstractCalculator
{
public:
virtual int getResult() // 扩展getResult方法
{
return x + y;
}
};
class SubCalculator :public AbstractCalculator
{
public:
virtual int getResult()
{
return x - y;
}
};
int main(int argc, char *argv[])
{
AbstractCalculator *ptr = new AddCalculator; // 创建一个加法
ptr->Set_Val(10, 20);
cout << "x+y = " << ptr->getResult() << endl;
delete ptr;
ptr = new SubCalculator; // 创建一个减法
ptr->Set_Val(10, 20);
cout << "x-y = " << ptr->getResult() << endl;
delete ptr;
system("pause");
return 0;
}
实现虚析构函数: 在基类的析构函数上加上virtual将其修饰为虚析构函数,其解决的问题是父类指针释放子类对象时,无法释放掉子类对象中的数据,或者说无法调用到子类对象的析构函数,我们可以利用虚析构来解决这个问题.
#include <iostream>
using namespace std;
class Animal
{
public:
// 此处加上virtual声明为虚析构函数
virtual ~Animal() { cout << "Animal back" << endl; }
};
class Cat :public Animal
{
public:
char *m_name;
public:
Cat(const char *name)
{
this->m_name = new char[strlen(name) + 1];
strcpy(this->m_name, name);
}
~Cat()
{
cout << "Cat back" << endl;
if (this->m_name != NULL)
{
delete[] this->m_name;
this->m_name = NULL;
}
}
};
int main(int argc, char *argv[])
{
Animal *ptr = new Cat("Tomcat");
delete ptr;
system("pause");
return 0;
}
实现纯虚析构函数: 如果函数中出现了纯虚析构函数,那么这个类也算抽象类,不可实例化对象,纯虚析构函数必须要存在实现,并且实现代码必须在类外,因为类内被定义为了纯虚析构函数,所以只能在类外部完成了.
#include <iostream>
using namespace std;
class Animal
{
public:
// 此处加上 virtual 声明为纯虚析构函数
virtual ~Animal() = 0 ;
};
Animal::~Animal()
{
// 纯虚析构函数实现
cout << "Animal back" << endl;
}
class Cat :public Animal
{
public:
char *m_name;
public:
Cat(const char *name)
{
this->m_name = new char[strlen(name) + 1];
strcpy(this->m_name, name);
}
~Cat()
{
cout << "Cat back" << endl;
if (this->m_name != NULL)
{
delete[] this->m_name;
this->m_name = NULL;
}
}
};
int main(int argc, char *argv[])
{
Animal *ptr = new Cat("Tomcat");
delete ptr;
system("pause");
return 0;
}
8.5 C++ 继承与多态的更多相关文章
- Objective-C中的继承和多态
面向对象编程之所以成为主流的编程思想和他的继承和多态是分不开的,只要是面向对象语言都支持继承和多态,当然不同的OOP语言之间都有其特点.OC中和Java类似,不支持多重继承,但OOP语言C++就支持多 ...
- java中抽象、分装、继承和多态的理解
1.抽象.封装装.继承和多态是java面向对象编程的几大特点. 抽象:所谓抽象就是对某件事务,我们忽略我们不关心不需要的部分,提取我们想要的属性和行为,并且以代码的形式提现出来:例如我们需要对一个学生 ...
- [转] JS中简单的继承与多态
这里讲了一个最最最简单的JS中基于原型链的继承和多态. 先看一下以下这段代码的实现(A是“父类”,B是“子类”): var A = function(){ this.value = 'a'; this ...
- 网络电视精灵~分析~~~~~~简单工厂模式,继承和多态,解析XML文档,视频项目
小总结: 所用技术: 01.C/S架构,数据存储在XML文件中 02.简单工厂模式 03.继承和多态 04.解析XML文档技术 05.深入剖析内存中数据的走向 06.TreeView控件的使用 核心: ...
- OC的封装、继承与多态
面向对象有三大特征:封装.继承和多态. 一.封装 封装是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法来实现对内部信息的操作和访问.简而言之,信息隐藏,隐 ...
- 2、C#面向对象:封装、继承、多态、String、集合、文件(上)
面向对象封装 一.面向对象概念 面向过程:面向的是完成一件事情的过程,强调的是完成这件事情的动作. 面向对象:找个对象帮你完成这件事情. 二.面向对象封装 把方法进行封装,隐藏实现细节,外部直接调用. ...
- Java学习笔记 07 接口、继承与多态
一.类的继承 继承的好处 >>使整个程序架构具有一定的弹性,在程序中复用一些已经定义完善的类不仅可以减少软件开发周期,也可以提高软件的可维护性和可扩展性 继承的基本思想 >>基 ...
- JavaScript 面向对象程序设计(下)——继承与多态 【转】
JavaScript 面向对象程序设计(下)--继承与多态 前面我们讨论了如何在 JavaScript 语言中实现对私有实例成员.公有实例成员.私有静态成员.公有静态成员和静态类的封装.这次我们来讨论 ...
- Java继承和多态实例
我们知道面向对象的三大特性是封装.继承和多态.然而我们有时候总是搞不清楚这些概念.下面对这些概念进行整理, 为以后面向抽象的编程打下坚实的基础. 封装的概念还是很容易理解的.如果你会定义类,那么相信你 ...
- python基础——继承和多态
python基础——继承和多态 在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类.父类或超类 ...
随机推荐
- 低风险稳健策略:BTC套利策略
更多精彩内容,欢迎关注公众号:数量技术宅,也可添加技术宅个人微信号:sljsz01,与我交流. 币安零手续费带来的机会 从7月8日的20点开始,币安推出了BTC现货交易零手续费的优惠活动,不论是Mak ...
- 海外加速,让你拥有和 Steam 一样的高速下载
Hello 各位亲爱的观众老爷们,好久不见呀. 暗影界的大门开了,育碧的限时原价结束了,美末 2 都拿年度游戏奖了,你们有猜到二狗子现在哪里么?听了不要吓一跳,二狗子刚刚抵达夜之城了!什么,你问二狗子 ...
- three.js 视频融合
MixVideo.js代码: //视频融合 import * as THREE from '../build/three.module.js'; import { API } from '../js. ...
- 【Logging 日志库】Cpp 日志库 boost::log 以及 glog 的对比
日志能方便地诊断程序原因.统计程序运行数据,是大型软件系统必不可少的组件之一.本文将从设计上和功能上对比 C++ 语言常见的两款日志库: boost::log 和 google-glog . 设计 b ...
- vivo悟空活动中台-打造 Nodejs 版本的MyBatis
经典的架构设计可以跨越时间和语言,得以传承. -- 题记 一.背景 悟空活动中台技术文章系列又和大家见面了,天气渐冷,注意保暖. 在往期的系列技术文章中我们主要集中分享了前端技术的方方面面,如微组件的 ...
- idea创建父子项目
1. 首先创建大的project 父工程: 2. 点击下一步之后: 3. 点击下一步,填写项目存放地址,点击finish: 4. 完成之后删除不需要的文件,保留pom文件,检查对应的jar和spri ...
- vue学习笔记 十二、通过计算属性获取定义的状态数据
系列导航 vue学习笔记 一.环境搭建 vue学习笔记 二.环境搭建+项目创建 vue学习笔记 三.文件和目录结构 vue学习笔记 四.定义组件(组件基本结构) vue学习笔记 五.创建子组件实例 v ...
- P1616-DP【橙】
这道题好几天前就写出了记搜代码,但是理论上空间恰好够,实际上不论是用new-delete还是malloc-free,都有1~2个点MLE了(最抽象的是一开始MLE两个点,我把数组两个下标调换顺序后理应 ...
- 线性代数 · 矩阵 · Matlab | Moore-Penrose 伪逆矩阵代码实现
背景 - Moore-Penrose 伪逆矩阵: 对任意矩阵 \(A\in\mathbb C^{m\times n}\) ,其 Moore-Penrose 逆矩阵 \(A^+\in\mathbb C^ ...
- SV Interface and Program
内容 验证平台与待测设计的连接 VTB driver和dut之间的连线通过tb中声明wire连线 通过例化dut的方式进行连接 A module的input连接到B module的output SVT ...