版权声明:本文为博主原创文章,未经博主同意不得转载。 https://blog.csdn.net/scottly1/article/details/31371611

OOP概述

面向对象程序设计(object-oriented programming)的核心思想是数据抽象继承动态绑定

1.继承

类的一种层次关系,通常在层次关系的根部有一个基类,其它类则直接或间接的继承基类而来。这些继承而来的类称为派生类

基类希望它的派生类自己定义适合自身的版本号的函数。基类就将函数声明为虚函数,加上virtualkeyword。

2.动态绑定

通过动态绑定,能够使用同一段代码处理基类和子类对象。

在C++中。当我们使用基类的引用或指针调用一个虚函数时会发生动态绑定。有虚函数(virtual)才会发生动态绑定。

在C++中,基类必须将它的两种成员函数区分开,一种是希望派生类进行覆盖的函数。一种是希望派生类直接继承而不覆盖的函数。

当且仅当通过指针或引用对虚函数调用时会在执行时被解析。

3.派生类构造函数

派生类中含有从基类继承而来的成员。派生类必须使用基类的构造函数来初始化它的基类部分。

派生类能够訪问基类的公有(public)成员和受保护(protected)成员。

4.纯虚函数

在函数体声明最后写=0,就可以将一个函数声明为纯虚函数。

含有纯虚函数的类是抽象基类。抽象基类仅仅负责定义接口,兴许的其它类能够覆盖该接口。

不能直接创建一个抽象基类的对象(含有纯虚函数的类不能直接实例化)。

派生类假设未定义继承而来的纯虚函数,则派生类也是抽象类。不能实例化。

5.类的作用域

每一个类有自己的作用域,在这个作用域内我们定义类的成员。

当存在继承关系时,派生类作用域嵌套在基类作用域内,假设一个名字在派生类的作用域内无法解析,则编译器将继续在外层的基类中寻找该名字的定义。

派生类的成员将隐藏同名的基类成员。

6.隐藏、覆盖。重载的差别:

(覆盖即派生类自己实现了基类中同名的函数(虚函数),
函数覆盖发生在父类与子类之间。其函数名、參数类型、返回值类型必须同父类中的相相应被覆盖的函数严格一致,覆盖函数和被覆盖函数仅仅有函数体不同)

仅仅要基类在定义成员函数时已经声明了virtualkeyword,在派生类实现的时候覆盖该函数时。virtualkeyword可加可不加,不影响多态的实现。
easy与隐藏混淆:
隐藏是指派生类的函数屏蔽了与其同名的基类函数。规则例如以下: 
1) 假设派生类的函数与基类的函数同名。可是參数不同。此时,不论有无virtualkeyword,基类的函数将被隐藏(注意别与重载混淆)。

 
2) 假设派生类的函数与基类的函数同名,而且參数也同样。可是基类函数没有virtualkeyword。此时。基类的函数被隐藏(注意别与覆盖混淆)。

比方,在以下的程序中:

#include <iostream.h>
class Base
{
public:
virtual void f(float x){ cout << "Base::f(float) " << x << endl; }
void g(float x){ cout << "Base::g(float) " << x << endl; }
void h(float x){ cout << "Base::h(float) " << x << endl; }
}; class Derived : public Base
{
public:
virtual void f(float x){ cout << "Derived::f(float) " << x << endl; }
void g(int x){ cout << "Derived::g(int) " << x << endl; }
void h(float x){ cout << "Derived::h(float) " << x << endl; }
};

通过分析可得: 
1) 函数Derived::f(float)覆盖了Base::f(float)。 
2) 函数Derived::g(int)隐藏了Base::g(float),注意。不是重载。 
3) 函数Derived::h(float)隐藏了Base::h(float),而不是覆盖。 

7.样例

test.h

#ifndef _TEST_H
#define _TEST_H using namespace std;
#include <string> class Animal
{
public:
Animal();
Animal(int a);
virtual ~Animal(); virtual void shout();
virtual void fight() = 0;
void eat();
void sleep();
protected:
int age;
}; class Person : public Animal
{
public:
Person();
Person(int a, string n);
~Person(); virtual void shout();//Cover!
//virtual void shout()const;//Hide!
virtual void fight();//Cover
void eat(string &n);//Hide not override!
void sleep();//Hide not Cover!
void show();
private:
//int age;//Hide!
string name;
}; #endif

test.cpp

#include <iostream>
#include "test.h" Animal::Animal():age(0)
{
cout << "Animal 1" << endl;
} Animal::Animal(int a):age(a)
{
cout << "Animal 2" << endl;
} Animal::~Animal()
{
cout << "~ Animal " << endl;
} void Animal::shout()
{
cout << "Animal Shout!" << endl;
} void Animal::eat()
{
cout << "Animal eat!" << endl;
} void Animal::sleep()
{
cout << "Animal sleep!" << endl;
} //---------------------------------------------------------------- Person::Person()
{
cout << "Person 1" << endl;
} Person::Person(int a, string n):Animal(a), name(n)//call Base class Counstruction Fun
{
cout << "Person 2" << endl;
} Person::~Person()
{
cout << "~ Person " << endl;
} void Person::shout()
{
cout << "Person Shout!" << endl;
} void Person::fight()
{
cout << "Person fight!" << endl;
} /*
void Person::shout()const
{
cout << "const Person Shout!" << endl;
}
*/ void Person::show()
{
cout << "I'm Person, Age: " << age << " Name: " << name << endl;
} void Person::eat(string &n)
{
cout << "Person: " << name << " eat!" << endl;
} void Person::sleep()
{
cout << "Person sleep!" << endl;
}

main.cpp

#include <iostream>
#include "test.h" int main()
{
Animal *p = new Person(20, "July");
p->shout();//run time bind!
p->fight();
p->eat();
p->sleep();
delete p;//~ Animal
//when add virtual before ~Animal() will output : ~ Person ~ Animal
//Animal *p = new Animal(20, "July"); the class has pure virtual functions cannot init! //if shout() is declared as : void shout(); p->shout() output :Animal shout not run time bind! /*
Person p(20, "Mike");
Animal &refP = p;
refP.shout();
*/ // p->show(); Error Animal has no number of show return 0;
}

执行结果:

Animal 2
Person 2
Person Shout!
Person fight!
Animal eat!
Animal sleep!
~ Person 
~ Animal

能够得出这样一个结论,被隐藏的函数是不能实现多态的。仅仅有覆盖virtual函数才干。

另外。基类析构函数须要加virtual。以便于正确的调用基类与派生类的析构函数。假设不加,delete p仅仅会输出:

~Animal。而不会调用派生类的析构函数。

C++ Primer笔记14_面向对象程序设计的更多相关文章

  1. (C/C++学习笔记) 十七. 面向对象程序设计

    十七. 面向对象程序设计 ● 面向对象程序设计的基本概念 ※ 类实际上是一种复杂的数据类型,它不仅包含不同类型的数据,还包含对这些数据的一些必要的操作. 而对象则是这种复杂的数据类型的一个变量. 类是 ...

  2. OOP_面向对象程序设计概述

    李际军老师"面向对象程序设计"课程第一课笔记整理 面向对象程序设计概述 20世纪90年代以来面向对象程序设计(Object Oriented Programming, 简称OOP) ...

  3. 初探C++Primer(15.面向对象程序设计)

    最近在恶补OOP相关知识,很遗憾学校的课没选上,于是只能上网购进C++Primer一本,开始重学C++之旅... (壮哉我大ZJU,网购半天到货XDD) 学习路线 7.类->13.类设计者的工具 ...

  4. 面向对象程序设计-C++ Stream & Template & Exception【第十五次上课笔记】

    这是本门<面向对象程序设计>课最后一次上课,刚好上完了这本<Thinking in C++> :) 这节课首先讲了流 Stream 的概念 平时我们主要用的是(1)在屏幕上输入 ...

  5. C++ Primer 5th 第15章 面向对象程序设计

    面向对象程序设计的核心思想是:数据抽象.继承和动态绑定. 数据抽象:将类的接口与实现分离: 继承:定义相似类型并对相似关系建模: 动态绑定:一定程度上上忽略相似类型间的区别,用同一方式使用它们. 1. ...

  6. [Python学习笔记][第六章Python面向对象程序设计]

    1月29日学习内容 Python面向对象程序设计 类的定义与使用 类定义语法 使用class关键词 class Car: def infor(self): print("This is ca ...

  7. {key}面向对象程序设计-C++ polymorphism 【第十三次上课笔记】

    Peronal Link: http://segmentfault.com/a/1190000002464822 这节课讲了本门课程 面向对象程序设计中最为重要的一个部分 - 多态 /******** ...

  8. [C++ Primer] : 第15章: 面向对象程序设计

    OOP: 概述 面向对象程序设计的核心思想是数据抽象, 继承和动态绑定. 通过数据抽象, 我们可以实现类的接口与实现的分离; 使用继承, 可以定义相似的类型并对其相似关系建模; 使用动态绑定, 可以在 ...

  9. C++面向对象程序设计学习笔记(1)

    基本概念 对象: 面向对象程序设计中,对象是描述其属性的数据以及对这些数据施加的一组操作封装在一起构成的统一体,每个对象都是由数据和操作代码两部分构成的. 类: 面向对象程序设计中,类是具有相同的数据 ...

随机推荐

  1. CentOS-6.*安装配置SVN

    安装说明 系统环境:CentOS-6.3 安装方式:yum install (源码安装容易产生版本兼容的问题) 安装软件:系统自动下载SVN软件 检查已安装版本 #检查是否安装了低版本的SVN [ro ...

  2. CentOS 加载/挂载光驱

    1.mkdir /mnt/cdrom 2.mount /dev/cdrom /mnt/cdrom 3.挂载      umount /dev/cdrom /mnt/cdrom

  3. Atitit.导出excel报表的设计与实现java .net php 总结

    Atitit.导出excel报表的设计与实现java .net php 总结 1. 导出报表 表格的设计要素1 1.1. 支持通用list<Map>转换1 1.2. 对于空列是否输出1 1 ...

  4. Nginx https加密以及nginx日志配置与管理

    Nginx https加密以及nginx日志配置与管理 使用Nginx的优点Nginx作为WEB服务器,Nginx处理静态文件.索引文件.自动索引的效率非常高.Nginx作为代理服务器,Nginx可以 ...

  5. java - day10 - uptest

    package day03; public class UpTest { public static void main(){ Aoo o = new Aoo(); o.a = 3; o.b = 3; ...

  6. 43. Spring Boot动态数据源(多数据源自动切换)【从零开始学Spring Boot】

    [视频&交流平台] àSpringBoot视频 http://study.163.com/course/introduction.htm?courseId=1004329008&utm ...

  7. C/C++程序开发中实现信息隐藏的三种类型

    不管是模块化设计,还是面向对象设计.还是分层设计,实现子系统内部信息的对外隐藏都是最关键的内在要求.以本人浅显的经验,把信息隐藏依照程度的不同分成(1)不可见不可用(2)可见不可用(3)可见可用. 1 ...

  8. 水仙花数-python

    题目: 求999以内的水仙花数? 分析: 如果一个3位数等于其各位数字的立方和,则称这个数为水仙花数. 例如:1^3 + 5^3+ 3^3 = 153,因此153就是一个水仙花数 我们需计算出153的 ...

  9. CBV流程

    django CBV 源码分析 FBV和CBV FBV(function base views) 就是在视图里使用函数处理请求. 在之前django的学习中,我们一直使用的是这种方式,所以不再赘述. ...

  10. hdu 1853 (费用流 拆点)

    // 给定一个有向图,必须用若干个环来覆盖整个图,要求这些覆盖的环的权值最小. 思路:原图每个点 u 拆为 u 和 u' ,从源点引容量为 1 费用为 0 的边到 u ,从 u' 引相同性质的边到汇点 ...