0827,多态

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(); //隐藏 没有多态 (哥们真的烦,什么玩楞)

相关推荐
jianglq30 分钟前
C++20 协程:异步编程的新纪元
算法·c++20
guicai_guojia1 小时前
面试题篇: 跨域问题如何处理(Java和Nginx处理方式)
java·开发语言·nginx
Amagi.1 小时前
对比介绍Java Servlet API (javax.servlet)和Apache HttpClient这两个库
java·servlet·apache
wniuniu_1 小时前
动态规划前---选----
算法·动态规划
lzb_kkk2 小时前
【Redis】redis5种数据类型(哈希)
开发语言·redis·算法·缓存·哈希算法
鱼跃鹰飞2 小时前
Leetcode面试经典150题-202.快乐数
算法·leetcode·面试
鱼跃鹰飞2 小时前
Leetcode面试经典150题-82.删除排序链表中的重复元素II
算法·leetcode·面试
2401_858120263 小时前
探索Oracle数据库的多租户特性:架构、优势与实践
数据库·oracle·架构
易雪寒3 小时前
Maven从入门到精通(二)
java·maven
易雪寒3 小时前
Maven从入门到精通(三)
java·python·maven