版权声明:本文为博主原创文章,未经博主同意不得转载。 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. Atitit.attilax的 case list 项目经验 案例列表

    Atitit.attilax的 case list 项目经验 案例列表 1. Atian inputmethod 输入法3 2. Ati desktop engine桌面引擎3 3. Acc资金账户系 ...

  2. bzoj1670【Usaco2006 Oct】Building the Moat 护城河的挖掘

    1670: [Usaco2006 Oct]Building the Moat护城河的挖掘 Time Limit: 3 Sec  Memory Limit: 64 MB Submit: 387  Sol ...

  3. python 学习方法

    依据本人的学习经验,我总结了下面十点和大家分享: 1)学好python的第一步.就是立即到www.python.org站点上下载一个python版本号.我建议刚開始学习的人,不要下载具有IDE功能的集 ...

  4. IOS设计模式浅析之适配器模式(Adapter)

    引言 在项目开发中,有时候会遇到这样的一种情景:需要使用以前开发的“一些现存的对象”,但是新环境中要求的接口是这些现存对象所不满足的.怎样应对这种迁移的需求?使得可以复用这些对象,以满足新的应用环境, ...

  5. \sum的写法

    \sum默认上下标是写在右上角和右下角的.在独立公式中,则是写在上面和下面的.对于行内公式,我们也可以强制用\limits让其上下表标出现在上面和下面.Note:\sum\nolimits的作用相当于 ...

  6. C++标准库之condition_variable

    conditon_variable(条件变量)用于线程间同步 condition_variable有5个函数,函数名及对应的功能如下: wait阻塞自己,等待唤醒 wait_for阻塞自己,等待唤醒, ...

  7. 第一百七十八节,jQuery-UI,知问前端--对话框 UI

    jQuery-UI,知问前端--对话框 UI 学习要点: 1.开启多个 dialog 2.修改 dialog 样式 3.dialog()方法的属性 4.dialog()方法的事件 5.dialog 中 ...

  8. 微信 oauth4

    4.最后 4. 使用access_token获取用户信息 请求方法: https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN& ...

  9. ios -bitmap上下文生成图片 生成水印

    - (void)test { // 0. 加载背景图片 UIImage *image = [UIImage imageNamed:@"psb"]; // 1.创建bitmap上下文 ...

  10. shell编程实战总结

    最近复习一下shell,顺便高级进阶一下,之前写脚本能简单尽量简单来,发现好多高深的东西还是没有理解,因此在这里记录一下整个过程并做相应的总结. 通过上代码的方式来介绍,后续可能会调整相应的排版 1. ...