02.0verride.cc
cpp
#include <iostream>
using std::cout;
using std::endl;
//-------------------------------//
class Base{
public:
Base(long x)
: _base(x)
{}
virtual void display() const{
cout << "Base::display()" << endl;
}
private:
long _base;
};
//-------------------------------//
class Derived
: public Base
{
public:
Derived(long base,long derived)
: Base(base)
, _derived(derived)
{}
//基类的display是虚函数
//派生类的display如果满足覆盖的条件,那么自动的也是虚函数
//覆盖的条件(形式完全一致) int display(){} 函数重载
void display() const override{
cout << "Derived::display()" << endl;
}
//override 对基类函数覆盖
private:
long _derived;
};
void print(Base * pbase){
pbase->display();
}
//-------------------------------//
void test(){
Derived d1(2,5);
cout<<endl;
Base* p=&d1;
p->display();
//基类指针调用派生类函数
cout<<sizeof(Base)<<endl;
//内存多了一个虚函数指针
cout<<sizeof(Derived)<<endl;
}
int main(void)
{
test();
return 0;
}
03.VTable.cc
cpp
#include <iostream>
using std::cout;
using std::endl;
//-------------------------------//
class Base{
public:
Base(long x)
: _base(x)
{}
virtual void display() const{
cout << "Base::display()" << endl;
}
//BASE定义了多个虚函数,依然只有一个虚函数指针
//只有一张虚函数表,表中存放了多个虚函数的入口地址
virtual void print() const{
cout << "Base::print()" << endl;
}
private:
long _base;
};
//-------------------------------//
class Derived
: public Base
{
public:
Derived(long base,long derived)
: Base(base)
, _derived(derived)
{}
//Derived类也 只有一张虚函数表
//继承多个有虚函数的基类,才会有多张虚表
void display() const override{
cout << "Derived::display()" << endl;
}
private:
long _derived;
};
void print(Base * pbase){
pbase->display();
}
//-------------------------------//
void test(){
Derived d1(2,5);
cout<<endl;
Base* p=&d1;
p->display();//对象必须通过指针或引用进行访问
//当直接进行操作时,编译器能给出确切的类型
//(指针不知道他指向的是个啥?)
//only 动态多态
d1.display();//理解为隐藏
Base base(10);
Base *p2=&base;
p2->display();
base.display();
cout<<endl;
cout<<sizeof(Base)<<endl;
cout<<sizeof(Derived)<<endl;
}
int main(void)
{
test();
return 0;
}
04.Grandpa.cc
cpp
#include <iostream>
using std::cout;
using std::endl;
//-------------------------------//
class Grandpa
{
public:
Grandpa(){ cout << "Grandpa()" << endl; }
~Grandpa(){ cout << "~Grandpa()" << endl; }
virtual void func1() {
cout << "Grandpa::func1()" << endl;
}
virtual void func2(){
cout << "Grandpa::func2()" << endl;
}
};
//一张虚函数表
//-------------------------------//
class Parent
: public Grandpa
{
public:
Parent(){
//通过this指针调用虚析构函数,会被解析为当前类的版本
cout << "Parent()" << endl;
func1();//构造函数中调用虚函数
}
~Parent(){
cout << "~Parent()" << endl;
func2();//析构函数中调用虚函数
}
};
//一张表,没有覆盖
//-------------------------------//
class Son
: public Parent
{
public:
Son() { cout << "Son()" << endl; }
~Son() { cout << "~Son()" << endl; }
virtual void func1() override {
cout << "Son::func1()" << endl;
}
virtual void func2() override{
cout << "Son::func2()" << endl;
}
};
//几张? 覆盖了
//-------------------------------//
void test(){
Son ss;
Grandpa* pg=&ss;
cout<<endl;
pg->func1();
pg->func2();
cout<<endl;
}
int main(void)
{
test();
return 0;
}
05.CallVirinMem.cc
cpp
#include <iostream>
using std::cout;
using std::endl;
class Base{
public:
Base(long x)
: _base(x)
{}
virtual void display() const{
cout << "Base::display()" << endl;
}
void func1(){
display();//this->display()
cout << _base << endl;
}
void func2(){
Base::display();
}
private:
long _base = 10;
};
//-------------------------------//
class Derived
: public Base
{
public:
Derived(long base,long derived)
: Base(base)
, _derived(derived)
{}
void display() const override{
cout << "Derived::display()" << endl;
}
private:
long _derived;
};
//-------------------------------//
void test(){
Base base(10);
Derived derived(1,2);
base.func1();
base.func2();
derived.func1();
derived.func2();
//-------------------------------//
/* Base::display() */
/* 10 */
/* Base::display() */
/* Derived::display() */
/* 1 */
/* Base::display() */
//-------------------------------//
}
int main(void)
{
test();
return 0;
}
06.PureVirtualFunc.cc
cpp
#include <iostream>
using std::cout;
using std::endl;
//-------------------------------//
class A{
public:
virtual void print() const=0;
virtual void hah() const=0;
};
//-------------------------------//
class B:public A{
public:
void print() const override{
cout<<"B:wang wang wang"<<endl;
}
void hah() const override{
cout<<"B hah:wang wang wang"<<endl;
}
};
//-------------------------------//
class C:public A{
public:
void print() const override{
cout<<"C:miao miao miao"<<endl;
}
};
//-------------------------------//
class D:public C{
public:
void hah() const override{
cout<<"D hah:miao miao miao"<<endl;
}
};
//-------------------------------//
void test(){
B b;
A* pa =&b;
pa->print();
pa->hah();
/* C c; */
D c;
pa=&c;
pa->print();
pa->hah();
}
int main(void)
{
test();
return 0;
}
07.Figure.cc
cpp
#include <iostream>
#include <string>
#include <math.h>
using std::cout;
using std::endl;
using std::string;
class Figure{
public:
virtual string getName() const=0;
virtual double getArea() const=0;
};
//-------------------------------//
class Rectangle:public Figure{
public:
Rectangle(double len,double wid)
:_lenght(len),_width(wid)
{}
string getName() const{
return "Rectangle";
};
double getArea() const{
return _lenght*_width;
}
private:
double _lenght;
double _width;
};
//-------------------------------//
class Circle:public Figure{
public:
Circle(double radius)
:_radius(radius)
{}
string getName() const{
return "circle";
};
double getArea() const{
return PI*_radius*_radius;
}
private:
double _radius;
static constexpr double PI=3.14;
};
//-------------------------------//
class Triangle:public Figure{
public:
Triangle(double a,double b,double c)
:_a(a),_b(b),_c(c)
{}
string getName() const{
return "triangle ";
};
double getArea() const{
double p=(_a+_b+_c);
return sqrt(p*(p-_a)*(p-_b)*(p-_c));
}
private:
double _a;
double _b;
double _c;
};
//-------------------------------//
void test(){
Rectangle r(3,5);
cout<<r.getName()<<"\t"<<r.getArea()<<endl;
Circle c(5);
cout<<c.getName()<<"\t"<<c.getArea()<<endl;
Triangle t(3,5,4);
cout<<t.getName()<<"\t"<<t.getArea()<<endl;
}
int main(void)
{
test();
return 0;
}
08.ProtectedAbstract.cc
cpp
#include <iostream>
using std::cout;
using std::endl;
class Base {
protected://只定义了保护属性的构造函数
Base(int base)
: _base(base)
{
cout << "Base()" << endl;
}
int _base;
};
//-------------------------------//
class Derived
: public Base {
public:
Derived(int base, int derived)
: Base(base)
, _derived(derived)
/* ,_b1(base)//Base 不能作为成员子对象*/
{ cout << "Derived(int,int)" << endl; }
void print() const
{
cout << "_base:" << _base
<< ", _derived:" << _derived << endl;
}
private:
int _derived;
/* Base _b1; */
//BAse中只定义了保护属性的构造函数,Tset无法调用BASe的构造函数
//直接创建或者作为成员子对象都不行
};
void test()
{
/* Base base(1);//error */
Derived derived(1, 2);
}
int main(void)
{
test();
return 0;
}
09.VirDestructor.cc
cpp
#include <iostream>
using std::cout;
using std::endl;
//-------------------------------//
class Base
{
public:
Base()
: _base(new int(10))
{ cout << "Base()" << endl; }
virtual void display() const{
cout << "*_base:" << *_base << endl;
}
//让~Derived覆盖BASE虚构函数在虚表中的地址
//这样pbase才能调用~Derived
/*virtual*/ ~Base(){
if(_base){
delete _base;
_base = nullptr;
}
cout << "~Base()" << endl;
}
private:
int * _base;
};
//-------------------------------//
class Derived
: public Base
{
public:
Derived()
: Base()
, _derived(new int(20))
{
cout << "Derived()" << endl;
}
virtual void display() const override{
cout << "*_derived:" << *_derived << endl;
}
//虚表覆盖 但是~BASE()的调用,不通过虚表
~Derived(){
if(_derived){
delete _derived;
_derived = nullptr;
}
cout << "~Derived()" << endl;
}
private:
int * _derived;
};
//-------------------------------//
void test(){
Base *pd=new Derived();
pd->display();
//内存泄露 直接24 间接8???
delete pd;
// 4 Base* -> no ~Derived
// 派生类的基类指针?调用不了派生类的析构函数(成员?
cout<<endl;
Derived *p1=new Derived();
delete p1;
}
int main(void)
{
test();
return 0;
}
10.CheckVtable.cc
cpp
#include <iostream>
using std::cout;
using std::endl;
//-------------------------------//
class Base{
public:
virtual void print() {
cout << "Base::print()" << endl;
}
virtual void display() {
cout << "Base::display()" << endl;
}
virtual void show() {
cout << "Base::show()" << endl;
}
private:
long _base = 10;
};
//-------------------------------//
class Derived
: public Base
{
public:
virtual void print() {
cout << "Derived::print()" << endl;
}
virtual void show() {
cout << "Derived::show()" << endl;
}
virtual void display() {
cout << "Derived::display()" << endl;
}
private:
long _derived = 100;
};
//-------------------------------//
void test(){
cout<<sizeof(Base)<<endl;
cout<<sizeof(Derived)<<endl;
//16(8+8) 24(8+16)
Derived d1;
long* pD=(long*)(&d1);
/* static int num=10; */
const char* b="hello";
/* cout<<&num<<endl; */
cout<<pD<<endl;
cout<<&b<<endl;
cout<<endl;
cout<<pD[0]<<endl;
cout<<pD[1]<<endl;
cout<<pD[2]<<endl;
//用C的方式 拆解内存布局 只关注内存
cout<<endl;
long* pVatable=(long*)(pD[0]);//指针指向三个连续的内存空间
cout<<pVatable[0]<<endl;
cout<<pVatable[1]<<endl;
cout<<pVatable[2]<<endl;
//虚表的三个元素 是函数指针
cout<<endl;
typedef void (*func)();
func f=(func)(pVatable[0]);
f();
f=(func)(pVatable[1]);
f();
f=(func)(pVatable[2]);
f();
//虚表顺序 根据基类定义顺序
}
int main(void)
{
test();
return 0;
}
11.MultiDerived.cc
cpp
#include <iostream>
using std::cout;
using std::endl;
class Base1
{
public:
Base1()
: _iBase1(10)
{
cout << "Base1()" << endl;
}
/*virtual*/ void f()
{
cout << "Base1::f()" << endl;
}
/*virtual*/ void g()
{
cout << "Base1::g()" << endl;
}
/*virtual*/ void h()
{
cout << "Base1::h()" << endl;
}
/*virtual*/ ~Base1() {}
private:
double _iBase1;
};
//---------------------------//
class Base2
{
public:
Base2()
: _iBase2(100)
{
cout << "Base2()" << endl;
}
virtual void f()
{
cout << "Base2::f()" << endl;
}
virtual void g()
{
cout << "Base2::g()" << endl;
}
virtual void h()
{
cout << "Base2::h()" << endl;
}
virtual ~Base2() {}
private:
double _iBase2;
};
//---------------------------//
class Base3
{
public:
Base3()
: _iBase3(1000)
{
cout << "Base3()" << endl;
}
virtual void f()
{
cout << "Base3::f()" << endl;
}
virtual void g()
{
cout << "Base3::g()" << endl;
}
virtual void h()
{
cout << "Base3::h()" << endl;
}
virtual ~Base3() {}
private:
double _iBase3;
};
//---------------------------//
class Derived
: public Base1
, public Base2
, public Base3
{
public:
Derived()
: _iDerived(10000)
{
cout << "Derived()" << endl;
}
void f()
{
cout << "Derived::f()" << endl;
}
virtual void g1()
{
cout << "Derived::g1()" << endl;
}
private:
double _iDerived;
};
//---------------------------//
int main(void)
{
cout << sizeof(Derived) << endl;
Derived d;
Base1* pBase1 = &d;
Base2* pBase2 = &d;
Base3* pBase3 = &d;
cout << "&Derived = " << &d << endl;
cout << "pBase1 = " << pBase1 << endl;
cout << "pBase2 = " << pBase2 << endl;
cout << "pBase3 = " << pBase3 << endl;
return 0;
}
12.MultiDerivedwithVir.cc
cpp
#include <iostream>
using std::cout;
using std::endl;
//------------------------------//
class A{
public:
virtual void a(){ cout << "A::a()" << endl; }
virtual void b(){ cout << "A::b()" << endl; }
virtual void c(){ cout << "A::c()" << endl; }
};
//------------------------------//
class B{
public:
virtual void a(){ cout << "B::a()" << endl; }
virtual void b(){ cout << "B::b()" << endl; }
void c(){ cout << "B::c()" << endl; }
void d(){ cout << "B::d()" << endl; }
};
//------------------------------//
class C
: public A
, public B
{
public:
virtual void a(){ cout << "C::a()" << endl; }
void c(){ cout << "C::c()" << endl; }
void d(){ cout << "C::d()" << endl; }
};
//2 表
//A C::a() C::c() B C::c()
//d()
//------------------------------//
//先不看D类
/* class D */
/* : public C */
/* { */
/* public: */
/* void c(){ cout << "D::c()" << endl; } */
/* }; */
void test(){
/* D c; */
C c;
c.a();//C::a() 隐藏
c.c();//C::c() 隐藏
c.d();//C::d() 隐藏,d对于C是普通成员函数
/* c.b(); //成员名访问冲突二义性 */
cout<<endl;
A* pa=&c;
pa->a();//C::a() 动态多态
pa->b();//A::b() 没有覆盖,会通过虚函数表
pa->c();//C::c() 动态多态
/* pa->d();//A类没有定义d函数,无法调用 */
cout << endl;
B* pb = &c;
pb->a(); //C::a() 多态
pb->b(); //B::b() 没有覆盖,虚表
pb->c(); //B::c() 普通函数c()
pb->d(); //B::d() 普通函数d()
cout << endl;
C * pc = &c;
pc->a(); //C::a() 通过虚表,没有触发动态多态
/* pc->b(); */ //访问二义性
pc->c(); //本质是虚函数,通虚表,没有触发动态多态
pc->d(); //隐藏 没有多态
}
int main(void)
{
test();
return 0;
}
作业:
01 C++中有哪几种多态?请详细说明一下
1,编译时多态/静态联编/多态
函数重载:允许在同一作用域内定义同名但参数列表不同的函数
运算符重载:允许定义或修改部分运算符的行为,使得自定义类型和内置类型能保持一致的操作
2,运行时多态/动态联编/多态
无法在编译过程中完成,只能程序运行时完成联编,C++通过虚函数实现
被激活的条件:
1,基类定义虚函数
2,派生类中要覆盖虚函数(覆盖虚函数表中的地址信息
3,创建派生类对象
4,基类的指针指向派生类对象(基类引用绑定派生类对象
5,通过基类指针(引用)调用虚函数
最终效果:基类指针(引用)调用到了派生类实现的虚函数(没有虚函数机制,基类指针只能调用到基类的函数成员
02 理解课上在GCC平台验证虚表的方式,以此为参考,验证一下虚表在内存中的哪个区域 *pD=1//段错误很想你
cpp
#include <iostream>
using std::cout;
using std::endl;
//-------------------------------//
class Base{
public:
virtual void print() {
cout << "Base::print()" << endl;
}
virtual void display() {
cout << "Base::display()" << endl;
}
virtual void show() {
cout << "Base::show()" << endl;
}
private:
long _base = 10;
};
//-------------------------------//
class Derived
: public Base
{
public:
virtual void print() {
cout << "Derived::print()" << endl;
}
virtual void show() {
cout << "Derived::show()" << endl;
}
virtual void display() {
cout << "Derived::display()" << endl;
}
private:
long _derived = 100;
};
//-------------------------------//
void test(){
cout<<sizeof(Base)<<endl;
cout<<sizeof(Derived)<<endl;
//16(8+8) 24(8+16)
Derived d1;
long* pD=(long*)(&d1);
/* static int num=10; */
const char* b="hello";
/* cout<<&num<<endl; */
cout<<pD<<endl;
cout<<&b<<endl;
}
int main(void)
{
test();
return 0;
}
03 带虚函数的多继承结构下,虚函数地址的存放规则是怎样?利用VS验证规则
/d1reportAllClassLayout
规则:
1,每个基类(定义了虚函数的)都有自己的虚函数表(派生类继承基类的虚表,如果自身定义了,还有自己的虚表
2,派生类如果有自己的虚函数,会被加到第一个虚函数表之中(希望尽快访问到函数
3,内存布局中,其基类的布局按照基类被声明时的吮吸排列(但,有虚函数的基类会往上放(希望尽快访问到虚函数
4,派生类会覆盖基类的虚函数,只有第一个虚函数表中存放的是真实的 被覆盖的函数的地址,其他的虚函数表中,对应位置存放的并不是真实的对于的虚函数的地址,而是一条跳转指令------指示到哪里去寻找被覆盖的虚函数的地址
#烦的很!!!!
cpp
1>class Base1 size(8):
1> +---
1> 0 | _iBase1
1> +---
1>class std::is_error_code_enum<char const *> size(1):
1> +---
1> 0 | +--- (base class std::integral_constant<bool,0>)
1> | +---
1> +---
1>class Base2 size(16):
1> +---
1> 0 | {vfptr}
1> 8 | _iBase2
1> +---
1>Base2::$vftable@:
1> | &Base2_meta
1> | 0
1> 0 | &Base2::f
1> 1 | &Base2::g
1> 2 | &Base2::h
1> 3 | &Base2::{dtor}
1>Base2::f this adjustor: 0
1>Base2::g this adjustor: 0
1>Base2::h this adjustor: 0
1>Base2::{dtor} this adjustor: 0
1>Base2::__delDtor this adjustor: 0
1>Base2::__vecDelDtor this adjustor: 0
1>class Base3 size(16):
1> +---
1> 0 | {vfptr}
1> 8 | _iBase3
1> +---
1>Base3::$vftable@:
1> | &Base3_meta
1> | 0
1> 0 | &Base3::f
1> 1 | &Base3::g
1> 2 | &Base3::h
1> 3 | &Base3::{dtor}
1>Base3::f this adjustor: 0
1>Base3::g this adjustor: 0
1>Base3::h this adjustor: 0
1>Base3::{dtor} this adjustor: 0
1>Base3::__delDtor this adjustor: 0
1>Base3::__vecDelDtor this adjustor: 0
1>class Derived size(48):
1> +---
1> 0 | +--- (base class Base2)
1> 0 | | {vfptr}
1> 8 | | _iBase2
1> | +---
1>16 | +--- (base class Base3)
1>16 | | {vfptr}
1>24 | | _iBase3
1> | +---
1>32 | +--- (base class Base1)
1>32 | | _iBase1
1> | +---
1>40 | _iDerived
1> +---
1>Derived::$vftable@Base2@:
1> | &Derived_meta
1> | 0
1> 0 | &Derived::f
1> 1 | &Base2::g
1> 2 | &Base2::h
1> 3 | &Derived::{dtor}
1> 4 | &Derived::g1
1>Derived::$vftable@Base3@:
1> | -16
1> 0 | &thunk: this-=16; goto Derived::f
1> 1 | &Base3::g
1> 2 | &Base3::h
1> 3 | &thunk: this-=16; goto Derived::{dtor}
04 今天最后一节课讲到的,带虚函数的多继承体系下,各种调用情况,完成剩余的情况分析
cpp
B* pb = &c;
pb->a();
pb->b();
pb->c();
pb->d();
cout << endl;
C * pc = &c;
pc->a();
pc->b();
pc->c();
pc->d();
cout << endl;
B* pb = &c;
pb->a(); //C::a() 多态
pb->b(); //B::b() 没有覆盖,虚表
pb->c(); //B::c() 普通函数c()
pb->d(); //B::d() 普通函数d()
cout << endl;
C * pc = &c;
pc->a(); //C::a() 通过虚表,没有触发动态多态
/* pc->b(); */ //访问二义性
pc->c(); //本质是虚函数,通虚表,没有触发动态多态
pc->d(); //隐藏 没有多态 (哥们真的烦,什么玩楞)