IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++基础知识笔记(下) -> 正文阅读

[C++知识库]C++基础知识笔记(下)

继承与派生

派生类的构成:

(1)继承基类的成员

  • 默认情况派生类包含除构造和析构函数外的所有成员。
  • C++11可以使用using语句继承基类构造函数,但是只能初始化从基类继承的成员,导致派生类新数据只能类内初始化不能使用构造函数定制,因此一般不使用该继承,一般当派生不定义新数据时使用。语法:using 基类构造函数::基类构造函数;
    (2)改造基类的成员
  • 派生类中可以定义与基类成员同名新成员,从而将外层同名成员隐藏,但是可以基类名和作用域限定符可以访问隐藏的同名函数(基类的)例:c1.B:: fun1(); c1.A::fun1()。
    (3)添加新的成员

不同继承方式的影响

  • 派生类成员对基类的访问权限
  • 通过派生类对象对基类成员的访问权限

派生类初始化

  1. 单继承时构造函数语法:
    派生类名::派生类名(基类形参,本类成员形参):基类名(参数化列表),本类成员初始化表
    {
    //其他
    };
  2. 多继承派生类构造函数语法:
    派生类名::派生类明(参数表):基类名1(初始化参数),基类2(初始化参数)…
    {
    //其他
    };
  3. 有继承和组合的派生类的构造函数语法:
    派生类名::派生类名(形参表):基类1(参数),基类…,本类成员包括对象成员的初始化表
    {
    //其他
    };
    以上不不清晰,如果有连个point对象,那形参里int x ,int y写两次? 还是不清楚呀

派生类的复制构造函数

  • 一般编译器会在需要的时候生成隐含的复制构造函数,它先调用基类的复制构造函数,再为派生类新增的成员进行复制。
  • 如果自己在派生类定义构造函数,语法如下:
    C::C(const C &c1):B(c1){…}
    复制构造函数只能接受一个参数,既用来初始化派生类定义的成员,也将被传递给基类的复制构造爱函数。基类复制构造函数的形参类型是基类对象的引用,实参可以是派生类对象的引用。

派生类析构

  • 构造时先构造基类再构造派生类成员,析构的时候相反,先执行派生类析构函数体再调用基类析构函数。

类型转换

在这里插入图片描述
有点懵懂,函数参数是基类类型的指针,可以用派生类对象传入实参:理解来就是说,可以使用派生对对象初始化基类类类型的指针,把派生类对象转化为基类对象,然后因为基类对象除了自己共有接口外,也不知道派生类新定义的接口,固然不会调用,反过来基类对象就不能传给派生类指针,因为派生类印象中是有派生时的特有接口的,如果一旦调用就会在基类对象找不到,简而言之,可以以多充少富余不用,不能以少充多要用没有。

虚基类

概念引出:当派生类从多个基类派生时,而多个基类又又共同的基类,则共同基类成员将在二次派生时冗余等问题。

  • 语法:以virtual 说明继承方式
    class B: virtual public A
    注意:在第一级继承时就要将共同基类设计成虚基类。
  • 虚基类及其派生类构造函数
    建立对象时所指定的类称最远派生类,虚基类成员由最远派生类构造函数调用虚基类构造函数初始化,中间其他类对虚基类的构造函数调用会被忽略。

多态性

运算符重载

  • 重载函数属于静态的多态性,而虚函数、指针、引用与运行时多态性有关。
  • 不能重载的运算符有:“?:”、“::”、“.*”、"."。
  • 重载后运算符优先级和结合性不会改变。
  • 运算符重载是针对新类型数据的实际需要,对原有运算符进行适当的改造。

双目运算符重载为成员函数

语法: 函数类型 operator (空格)运算符(形参)
{
参数个数比原操作数个数少1(后置++和–除外)
}
A+B相当于A.operator +(B),operator +是A对象所属类的成员函数,操作数B作为为函数实参。

单目运算符重载为成员函数

如果要重载++或者–等单目运算符,使它可以实现oper++和++oper等表达式,其中oper为A类的对象,则++或–应该被重载为A类的成员函数。由于++oper和oper++都是对++重载,函数均为 operator ++,这样为了区分函数,只能用参数列表区分了,但参数列表也一样,没有参数。故,规定后置++多一个参数即:opetator ++(int)。

#include"stdafx.h"
#include<iostream>
using namespace std;
class Clock
{
private:
	int hour, minute, second;
public:
	Clock(int hour = 0, int minute = 0, int second = 0);
	void showtime();
	Clock &operator ++();
	Clock operator ++(int);
};
Clock::Clock(int hour , int minute , int second ) 
{
	if (hour >= 0 && hour < 24 && minute >= 0 && minute < 60 && second >= 0 && second < 60)
	    {this->hour = hour;
		this->minute = minute;
		this->second = second;}
	else  cout << "Time error" << endl;
}
void Clock::showtime(){
	cout << hour << ":" << minute << ":" << second<<endl;}
 Clock& Clock::operator ++()    //类型为 Clock& 
     { second++;
	 if (second == 60)
	 { second -= 60; minute++; if (minute == 60)
		 {minute -= 60; hour = (hour + 1) % 24 } }
	 return *this}
 Clock Clock::operator ++(int)
     { Clock old= *this; ++(*this); return old; }
 int main()
 { Clock myclock(23, 59, 59);
	 (myclock++).showtime();
	 (++myclock).showtime();
	 return 0;}

运行结果: 23:59:59 换行 0:0:1

运算符重载为非成员函数

  • 当运算符的左操作数不是类对象时,就无法将该运算符在类中进行重载,当运算符左操作数是类库对象等我们无法修改的类对象时,也不能修改类库添加操作符重载函数,为了解决以上问题,需要在类外对操作符进行重载,为了让重载函数具有访问类的权限,可以将它在类内声明为友元函数。
  • 函数参数个数与原操作数个数相同(后置++、–除外)
  • 后置单目运算符++、–形参列表中增加一个int,但不需要写形参名。

虚函数

虚函数、虚析构函数与虚基类

虚表与动态绑定

模板与群体数据

如果重载的函数解决问题的逻辑是一致的、函数体语句相同,只是处理的数据类型不同,那么写多个相同的函数体,是重复劳动,而且还可能因为代码的冗余造成不一致性,为此使用函数模板可以用同种方法处理不同类型的数据。

模板语法

语法: template<class/typename T>

  • 只有能够进行函数模板中运算的类型,可以作为类型实参,自定义的类,需要重载模板中的运算符,才能作为类型实参。

类模板

语法(代码为例):

#include <iostream>
#include <cstdlib>
using namespace std;
struct Student {
  int id;       //学号
  float gpa;    //平均分
}; 
template <class T>
class Store {//类模板:实现对任意类型数据进行存取
private:
    T item; // item用于存放任意类型的数据
    bool haveValue;  // haveValue标记item是否已被存入内容
public:
    Store();
    T &getElem();   //提取数据函数
    void putElem(const T &x);  //存入数据函数
};

template <class T>  
Store<T>::Store(): haveValue(false) { } 
template <class T>
T &Store<T>::getElem() {
    //如试图提取未初始化的数据,则终止程序
    if (!haveValue) {   
        cout << "No item present!" << endl;
        exit(1);    //使程序完全退出,返回到操作系统。
    }
    return item;        // 返回item中存放的数据 
}
template <class T>
void Store<T>::putElem(const T &x) {
    // 将haveValue 置为true,表示item中已存入数值   
    haveValue = true;   
    item = x;           // 将x值存入item
}
int main() {
    Store<int> s1, s2;  
    s1.putElem(3);  
    s2.putElem(-7);
    cout << s1.getElem() << "  " << s2.getElem() << endl;

    Student g = { 1000, 23 };
    Store<Student> s3;
    s3.putElem(g); 
    cout << "The student id is " << s3.getElem().id << endl;

    Store<double> d;
    cout << "Retrieving object D... ";
    cout << d.getElem() << endl;
   //d未初始化,执行函数D.getElement()时导致程序终止
    return 0;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-28 08:51:02  更:2021-08-28 08:51:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:52:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码