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++基类、派生类、虚函数的几个知识点的更多相关文章

  1. C++:抽象基类和纯虚函数的理解

    转载地址:http://blog.csdn.net/acs713/article/details/7352440 抽象类是一种特殊的类,它是为了抽象和设计的目的为建立的,它处于继承层次结构的较上层. ...

  2. C++基础知识 基类指针、虚函数、多态性、纯虚函数、虚析构

    一.基类指针.派生类指针 父类指针可以new一个子类对象 二.虚函数 有没有一个解决方法,使我们只定义一个对象指针,就可以调用父类,以及各个子类的同名函数? 有解决方案,这个对象指针必须是一个父类类型 ...

  3. (转)(C++)关于抽象基类和纯虚函数

    ★抽象类:一个类可以抽象出不同的对象来表达一个抽象的概念和通用的接口,这个类不能实例化(创造)对象. ★纯虚函数(pure virtual):在本类里不能有实现(描述功能),实现需要在子类中实现.例: ...

  4. C++学习笔记(十二):类继承、虚函数、纯虚函数、抽象类和嵌套类

    类继承 在C++类继承中,一个派生类可以从一个基类派生,也可以从多个基类派生. 从一个基类派生的继承称为单继承:从多个基类派生的继承称为多继承. //单继承的定义 class B:public A { ...

  5. C++入门经典-例8.9-抽象类,纯虚函数,创建纯虚函数

    1:包含有纯虚函数的类称为抽象类,一个抽象类至少具有一个纯虚函数.抽象类只能作为基类派生出的新的子类,而不能在程序中被实例化(即不能说明抽象类的对象),但是可以使用指向抽象类的指针.在程序开发过程中并 ...

  6. 继承虚函数浅谈 c++ 类,继承类,有虚函数的类,虚拟继承的类的内存布局,使用vs2010打印布局结果。

    本文笔者在青岛逛街的时候突然想到的...最近就有想写几篇关于继承虚函数的笔记,所以回家到之后就奋笔疾书的写出来发布了 应用sizeof函数求类巨细这个问题在很多面试,口试题中很轻易考,而涉及到类的时候 ...

  7. 自绘CListCtrl类,重载虚函数DrawItem

    //自绘CListCtrl类,重载虚函数DrawItem void CNewListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { // TOD ...

  8. C++中继承 声明基类析构函数为虚函数作用,单继承和多继承关系的内存分布

    1,基类析构函数不为虚函数 #include "pch.h" #include <iostream> class CBase { public: CBase() { m ...

  9. c++ 类内部函数调用虚函数

    做项目的过程中,碰到一个问题. 问题可以抽象为下面的问题: 普通人吃饭拿筷子,小孩吃饭拿勺子. class People { public: void eat() { get_util_to_eat( ...

随机推荐

  1. 51nod 1002 数塔取值问题 dp

    动态规划 1002 数塔取数问题 1.0 秒 131,072.0 KB 5 分 1级题   一个高度为N的由正整数组成的三角形,从上走到下,求经过的数字和的最大值. 每次只能走到下一层相邻的数上,例如 ...

  2. 响应式Web设计:构建令人赞叹的Web应用程序的秘诀

    骨架屏(Skeleton Screen) 参考博客:https://medium.com/@owencm/reactive-web-design-the-secret-to-building-web- ...

  3. ASP.NET Core MVC学习笔记

    最近由于疫情紧张,遂在家办公,在领导的带领下,学习了一下.Net Core MVC. 一,构建web应用 1.选择c#-所有平台-web  找到ASP.NET Core web应用程序 2.项目命名之 ...

  4. Apache Log4j 反序列化代码执行(CVE-2019-17571) 漏洞分析

    Apache Log4j 漏洞分析 仅用于研究漏洞原理,禁止用于非法用途,后果自负!!! CVE-2019-17571 漏洞描述 Log4j是美国阿帕奇(Apache)软件基金会的一款基于Java的开 ...

  5. C语言 getchar

    C语言 getchar getchar是从标准输入设备读取一个char. 案例 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #in ...

  6. Excel——排序筛选

    1,自定义排序:多个关键字,从右向左一一排序 * 按颜色排序 * 按自定义序列排序 *两列中,列一个中间数,升序 * 打印标题行 * 选中,定位条件(可见),选择 * 数值筛选(大于等于),文本筛选( ...

  7. Android实战项目——家庭记账本(一)

    今天是家庭记账本APP开发的第一天,主要是做了一部分UI设计,不得不说,虽然web开发和Android开发有很多相似的地方,但是一个Android APP是很难三个小时开发完成的. 通过今天的学习与开 ...

  8. Windos framework .net 3.5规则失败

    1. 安装的时候有一个.net警告,这里给后边造成了一个隐患,实际上是wondows少了一个framework .net的插件,跟SQLserver安装本身没关系,一开始忽略了,后边就报错了. 2.点 ...

  9. ArchLinux下electronssr无法启动的解决措施

    ArchLinux下electronssr无法启动的解决措施 今天重新配置electron-ssr时发现闪退(无法启动). 于是开始查错 首先是找到了目录位置 /usr/electron-ssr/el ...

  10. CentOS7配置ftp

    1.下载vsftpd yum install -y vsftpd 2.设置开机自启动 systemctl enable vsftpd.service 3.启动 systemctl start vsft ...