第15章 面向对象程序设计
2016-01-14 22:19
645 查看
面向对象的核心是:数据抽象、继承、动态绑定
数据抽象:将类的接口与实现分离
继承:对类型的相似关系进行定义建模
动态绑定:忽略相似类的区别,统一使用它们的对象
基类都应该定义一个虚函数,这样在delete一个指向派生类对象的基类指针所指向new分配的空间时,能会有理想的析构函数调用(先调用派生类的析构函数,再调用基类的。否则将会仅调用基类的析构函数)。
派生类覆盖基类的虚函数,可以使用(不必须,旧标准没有)override关键字,同时派生类的此函数自动成为virtual的,不管加不加virtual关键字。
final表明这个类不能被继承。
如果需要喜用被override的基类成员,需要加上基类的作用域Base::
派生类的对象和基类的对象之间不存在期望的类型转换,因为派生类赋值给基类的时候,实际发生的是执行拷贝构造函数等过程,最终得到一个新的基类对象。
如果虚函数=0,就是纯虚函数。有纯虚函数的类是抽象基类。我们不能创建抽象基类的对象。
protect成员对类的用户来讲是不可访问的
派生类protect继承基类,则基类的public成员降维成protect成员存在于派生类中
派生类的成员可以通过派生类的对象访问基类的protect成员(因为2中继承过来,相当于自己的protect成员),而不能通过基类的对象访问基类的protect成员(因为1)
private
private成员对用类的用户来讲是不可访问的。private继承过来的基类的所有成员在派生类中都将会是私有的。
派生类public继承的基类之间,才能够进行类型转换
提升基类成员的访问级别
如果派生类定义了和基类中名字相同的成员,则基类的成员在派生类的作用域中将会被隐藏。如果要使用,则可以通过基类的作用域进行调用。
基类的虚析构函数(哪怕=default)还会阻止合成的移动操作。(析构函数一般和合成的移动操作有冲突)所以派生类已没有合成的移动操作,一般应该重新定义如下:
数据抽象:将类的接口与实现分离
继承:对类型的相似关系进行定义建模
动态绑定:忽略相似类的区别,统一使用它们的对象
15.2基类与派生类
class Base { public: Base() = default; Base(int value) :value(value){} virtual int get_value() { return value; }; virtual ~Base() = default; private: int value; protected: void change_value() { value++; } };
基类都应该定义一个虚函数,这样在delete一个指向派生类对象的基类指针所指向new分配的空间时,能会有理想的析构函数调用(先调用派生类的析构函数,再调用基类的。否则将会仅调用基类的析构函数)。
class Derived final:public Base { public: Derived() = default; Derived(int value) :Base(value) {} int get_value() override { return value*value; } };
派生类覆盖基类的虚函数,可以使用(不必须,旧标准没有)override关键字,同时派生类的此函数自动成为virtual的,不管加不加virtual关键字。
final表明这个类不能被继承。
如果需要喜用被override的基类成员,需要加上基类的作用域Base::
15.2.3类型转换与继承
派生类的指针或引用可以隐式转换成基类的指针引用,反之则不行。派生类的对象和基类的对象之间不存在期望的类型转换,因为派生类赋值给基类的时候,实际发生的是执行拷贝构造函数等过程,最终得到一个新的基类对象。
15.3虚函数/抽象基类
我们如果想调用被override的虚函数,可以使用作用域运算符进行调用。如果虚函数=0,就是纯虚函数。有纯虚函数的类是抽象基类。我们不能创建抽象基类的对象。
15.5访问控制与继承
protectprotect成员对类的用户来讲是不可访问的
派生类protect继承基类,则基类的public成员降维成protect成员存在于派生类中
派生类的成员可以通过派生类的对象访问基类的protect成员(因为2中继承过来,相当于自己的protect成员),而不能通过基类的对象访问基类的protect成员(因为1)
private
private成员对用类的用户来讲是不可访问的。private继承过来的基类的所有成员在派生类中都将会是私有的。
派生类public继承的基类之间,才能够进行类型转换
提升基类成员的访问级别
class Base { public: std::size_t size() const { return n; } protected: std::size_t n; }; class Derived : private Base { public: //本来对于使用者是private的,但是提升到了public using Base::size; protected: //本来对于使用者是private的,但是提升到了protected using Base::n; };
15.6继承中类的作用域
在对象进行成员访问的时候,首先从其静态作用域中需要成员。如果找不到,去外层基类中进行查找。如果派生类定义了和基类中名字相同的成员,则基类的成员在派生类的作用域中将会被隐藏。如果要使用,则可以通过基类的作用域进行调用。
15.7构造函数与拷贝控制
基类为虚析构函数时,使用基类的指针或引用删除(delete)派生类对象时,才能正确执行派生类的析构函数。基类的虚析构函数(哪怕=default)还会阻止合成的移动操作。(析构函数一般和合成的移动操作有冲突)所以派生类已没有合成的移动操作,一般应该重新定义如下:
class Quote { public: Quote() = default; // memberwise default initialize Quote(const Quote&) = default; // memberwise copy Quote(Quote&&) = default; // memberwise copy Quote&operator=(const Quote&) = default; // copy assign Quote&operator=(Quote&&) = default; // move assign virtual~Quote() = default; // other members as before };
15.7.4继承的构造函数
默认、拷贝、移动构造函数将不会被继承。class Base { public: Base(int n) { cout << "base" << endl; } }; class Derived final:public Base { public: using Base::Base; //上边这个继承的基类构造函数会被编译器产生如下代码 //但是如果用户自定义了,基类的构造函数就会被覆盖 //Derived(int n) :Base(n) { cout << "derived" << endl; } };
相关文章推荐
- C语言中的顺序点
- android Wearable-Accessing the Wearable Data Layer and Syncing Data Items
- 解决select2 在easyui dialog中不显示下拉列表的问题
- LAMP
- 接口(interface)那点事
- POJ 1163 The Triangle
- 感悟一:习惯很重要
- 人脸识别 交叉验证函数crossvalind 的用法
- 深入hibernate的三种状态
- uva839 Not so Mobile
- hdoj3427Clickomania【记忆化搜索】
- Win7下Visual Studo 2010安装图解教程
- 机器学习中的 precision、recall、accuracy、F1 Score
- @GeneratedValue的用法
- mysql单表查询
- CustomViewAccessibilityActivity
- 简单技巧:引用 .txt 文件
- iPhone/Mac Objective-C 内存管理教程和原理剖析 [转]
- 抽象类那点事
- 你嘛,打鸡血容易吗