C++基类、派生类、虚函数的几个知识点
1.尽管派生类中含有基类继承来的成员,但派生类初始化这部分变量需要调用基类的构造函数。
class A
{
private:
int x;
virtual void f(){cout<<"A f"<<endl;}
public:
A(/* args */){x=;cout<<"A构造"<<endl;}
~A(){}
friend void p(const A& a){cout<<a.x;}
};
class B:A{
public:
void f() override {cout<<"B f"<<endl;}
operator A()const {}
};
int main()
{
B x;
system("pause");
return ;
}

2.如果基类定义了一个静态成员,则整个继承体系中只存在该成员的唯一定义。并且不论基类派生出多少派生类,该静态成员只存在唯一实例。
并且属性也一致。基类中某静态成员是public,派生类中也是public。如果基类中是private,那么派生类也无法调用该静态成员。
/* 基类的静态成员 */ #include<iostream> using namespace std; class base
{
public:
static int num; base()
{
num+=;
} ~base()
{
num-=;
}
}; // 基类定义的静态成员,被所有派生类共享
// 起到计数器的作用,自身还有所有派生类对象的个数
// 遵循私有 公有 保护的继承机制 访问不同
// 可以通过父类 子类对象访问 还可以通过父类 子类类名访问
int base::num = ;// 类的静态成员 class basenew : public base
{ }; class basenewx : public basenew
{ }; void main()
{
basenew *p = new basenew[]; base *p1 = new base[] basenewx *p2 = new basenewx[]; cout << p->num << endl;//
cout << p1->num << endl;//
cout << p2->num << endl;// cin.get();
}
3.如果不想让某个类被继承,在类名后加final关键字。

final除了可以修饰类外,还可以修饰成员函数。还可以指明某个基类的虚函数不能被其派生类版本覆盖,如下:
首先要明确覆盖(override)与重载(overload)的定义,区别出什么是覆盖和重载:
覆盖就是派生类中虚成员函数覆盖基类中同名且参数相同的成员函数。
class A
{
public:
A(/* args */){}
virtual void f()final {}
virtual ~A(){}
};
class B:public A{
public:
void f(int x){}//重载(overload)
void f(){} //覆盖(override,非法,因为A中的f声明了final)
};
4.派生类对象是基类对象,派生类中包含有基类的成员。基类对象不是派生类对象,它不能包含派生类型的成员。
派生类可以向基类转化(仅限指针和引用),基类不能向派生类转化(毕竟派生类有多余的数据,基类没法自己生成)
如果用派生类对象为一个基类对象初始化或者赋值,只有其中的基类部分会被拷贝/移动/赋值,它的派生类部分会被忽略。
class A
{
private:
int x;
public:
A(/* args */){x=;cout<<"A构造"<<endl;}
virtual ~A(){}
};
class B:public A{ };
int main()
{
A x;
B y;
A* p=&y;//正确,将基类指针指向派生类变量,派生类指针隐式转换为基类指针。
B* q=&x;//错误
system("pause");
return ;
}
5.动态绑定(即dynamic bninding)只有当我们通过指针或者引用调用虚函数时才会发生。
由于继承导致对象的指针和引用具有两种不同的类型:静态类型和动态类型。
静态类型:指针或者是引用声明时的类型。
动态类型:由实际指向的类型确定。
其中静态类型编译时就已经确定,动态类型只有到运行的时候才能知道。所以如果用普通类类型调用虚函数,编译时就会把要调用的虚函数版本确定下来。
class A
{
public:
A(/* args */){}
virtual void f(){cout<<"基类的f"<<endl;}
virtual ~A(){}
};
class B:public A{
public:
void f(){cout<<"派生类的f"<<endl;}
};
void F(A& p){
p.f();
}
int main()
{
A x;
B y;
F(x);
F(y);
system("pause");
return ;
}

可以看到同一个函数F,因为调用不同类型实参,最终在内部调用了不同版本的f函数,这就是动态绑定。
如果F的形参改成普通类型,那么两次都会调用基类的f函数,其中F(y)会把y隐式类型转换为一个A类型的临时变量传给形参。

6.如果一个派生类虚函数需要调用其基类版本,但没有使用“基类::”修饰,则运行时该调用会被解析为对其自身的调用,这将导致无限递归。
7.派生类中的虚函数可以在形参后加override,显式告知编译器该虚函数覆盖了其基类版本。
C++基类、派生类、虚函数的几个知识点的更多相关文章
- C++:抽象基类和纯虚函数的理解
转载地址:http://blog.csdn.net/acs713/article/details/7352440 抽象类是一种特殊的类,它是为了抽象和设计的目的为建立的,它处于继承层次结构的较上层. ...
- C++基础知识 基类指针、虚函数、多态性、纯虚函数、虚析构
一.基类指针.派生类指针 父类指针可以new一个子类对象 二.虚函数 有没有一个解决方法,使我们只定义一个对象指针,就可以调用父类,以及各个子类的同名函数? 有解决方案,这个对象指针必须是一个父类类型 ...
- (转)(C++)关于抽象基类和纯虚函数
★抽象类:一个类可以抽象出不同的对象来表达一个抽象的概念和通用的接口,这个类不能实例化(创造)对象. ★纯虚函数(pure virtual):在本类里不能有实现(描述功能),实现需要在子类中实现.例: ...
- C++学习笔记(十二):类继承、虚函数、纯虚函数、抽象类和嵌套类
类继承 在C++类继承中,一个派生类可以从一个基类派生,也可以从多个基类派生. 从一个基类派生的继承称为单继承:从多个基类派生的继承称为多继承. //单继承的定义 class B:public A { ...
- C++入门经典-例8.9-抽象类,纯虚函数,创建纯虚函数
1:包含有纯虚函数的类称为抽象类,一个抽象类至少具有一个纯虚函数.抽象类只能作为基类派生出的新的子类,而不能在程序中被实例化(即不能说明抽象类的对象),但是可以使用指向抽象类的指针.在程序开发过程中并 ...
- 继承虚函数浅谈 c++ 类,继承类,有虚函数的类,虚拟继承的类的内存布局,使用vs2010打印布局结果。
本文笔者在青岛逛街的时候突然想到的...最近就有想写几篇关于继承虚函数的笔记,所以回家到之后就奋笔疾书的写出来发布了 应用sizeof函数求类巨细这个问题在很多面试,口试题中很轻易考,而涉及到类的时候 ...
- 自绘CListCtrl类,重载虚函数DrawItem
//自绘CListCtrl类,重载虚函数DrawItem void CNewListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { // TOD ...
- C++中继承 声明基类析构函数为虚函数作用,单继承和多继承关系的内存分布
1,基类析构函数不为虚函数 #include "pch.h" #include <iostream> class CBase { public: CBase() { m ...
- c++ 类内部函数调用虚函数
做项目的过程中,碰到一个问题. 问题可以抽象为下面的问题: 普通人吃饭拿筷子,小孩吃饭拿勺子. class People { public: void eat() { get_util_to_eat( ...
随机推荐
- linux下搭建DHCP服务
一键搭建dhcpd服务脚本 [root@dhcp-server~]# cat auto_install_dhcpd.sh #!/bin/sh . /etc/init.d/functions #安装dh ...
- [Python]判断变量类型是否为List列表
用法:isinstance(变量,list) li = [1,2,3] print(type(li)) if isinstance(li,list): print("This is a Li ...
- CoachAI 2019年12月~2020年3月实习总结
CoachAI 2019年12月~2020年3月实习总结 一句话总结: 方向对口,大有所得. CoachAI公司简介 CoachAI是一家做在线健身的公司,目前在手机端和IOS端都有自己的服务,并 ...
- redis教程-redis环境搭建安装(qq:1324981084)
需要整套redis缓存高可用集群教学视频的加qq:1324981084,本套视频从安装到集群的搭建和源码的解析,从零基础讲解. 1.利用命令将redis下载到/usr/local/文件夹下: wget ...
- Sunset: dusk: Vulnhub Walkthrough
靶机链接: https://www.vulnhub.com/entry/sunset-dusk,404/ 主机IP扫描: IP端口扫描: 21 端口 pyftpdlib 1.5.5 版本漏洞 25 ...
- Hadoop之HDFS扩容方法
HDFS就是用来存取数据的,那么当数据太多的时候存不下,我们必需扩充硬盘容量,或者换个更大的硬盘. 由于它是分布式文件系统,有两种扩充HDFS集群容量的方法:横向扩容和纵向扩容 横向扩容 横向扩容就是 ...
- MFC/QT 学习笔记(四)——MFC基于对话框学习控件(下)
//5.列表控件 ListControl 属性 报表模式 view:Report:添加变量 //Cdemo5Dlg.cpp ps:资源视图 右键 类向导 成员变量 查看对象所属类 // TODO: 在 ...
- asp.net abp模块化开发之通用树2:设计思路及源码解析
一.前言 上一篇大概说了下abp通用树形模块如何使用,本篇主要分析下设计思路. 日常开发中会用到很多树状结构的数据,比如:产品的多级分类.省市区县,大多数系统也会用到类似“通用字典/数据字典”的功能, ...
- PMP-番外篇-PMP工具与技术目录
########################################################### 这里先总结所有工具和技术,让大家有一个整体的概念. 也可以当作一个工具和技术查询 ...
- linux文件、文件夹操作
1. pwd 查看当前所在的路径 2. ls 显示文件列表 ls -l 显示文件列表以及详情 ls -la 显示所有文件列表以及详情(包含隐藏文件) 注意:ls -l 相当于ll 例如 ...