嵌入式C++(四)

一、继承

1.1 继承中的类型兼容性原则

概念:类型兼容性原则是指在需要基类对象的地方,我们都可以直接使用公有派生类对象,通过公有继承,我
们可以得到基类中除了构造函数,析构函数外的所有成员,这样,凡是基类可以解决的问题,派生类都可以解
决。

(1)子类对象可以当成父类对象使用,子类对象是一种特殊的父类。
(2)父类指针可以直接指向子类对象
(3)父类引用可以直接引用派生类对象

在这里插入图片描述

#include <iostream>
using namespace std;

class Parent
{
    protected:
        int m_a;
        int m_b;
    public:
        Parent()
        {
            cout<<"Parent的无参构造函数"<<endl;
        }
        Parent(const Parent &obj)
        {
            cout<<"Parent的拷贝构造函数"<<endl;
            m_a = obj.m_a;
            m_b = obj.m_b;
        }
        void SetAB(int a,int b)
        {
            m_a = a;
            m_b = b;
        }
        void print()
        {
            cout<<"m_a = "<<this->m_a<<endl;
            cout<<"m_b = "<<this->m_b<<endl;
        }

};
class Child:public Parent
{
    private:
        int m_c;
    public:
        void SetC(int c)
        {
            this->m_c = c;
        }
        void printC()
        {
            cout<<"c = "<<m_c<<endl;
        }
};

int main(int argc, char const *argv[])
{
	/*
	Parent p1;
	p1.SetAB(1,2);
	p1.print();
	*/
    Child c;
    c.SetAB(10,20);
    c.SetC(30);
    c.print();
    c.printC();

    // Parent &p = c;
    // p.printC();//不能使用
    
    //Child *pc = &c;
	//Parent *p = &c;
	//p->SetAB(1,2);
	//p->SetC(20);
    return 0;
}

1.2 多继承

(1) 概念

派生类中如果只有一个基类,称为单继承,除此之外,c++中还支持多继承,每一个派生类可以继承多个基
类。

(2)多继承的语法

用逗号将继承的基类隔开。

#include <iostream>
using namespace std;
class AirPlane
{
    protected:
        int high;
    public:
        AirPlane()
        {
            cout<<"飞机的构造函数"<<endl;
            high = 100;
        }
        void show()
        {
            cout<<"飞机的高度"<<high<<endl;
        }
};

class Ship
{
    protected:
        int speed = 40;
    public:
        Ship()
        {
            cout<<"轮船的构造函数"<<endl;
        }

        void show()
        {
            cout<<"航行的速度:"<<speed<<endl;
        }
};

class WaterPlane:public Ship,public AirPlane
{
    public:
        WaterPlane()
        {
            cout<<"水上飞机的构造函数"<<endl;
        }
};


int main(int argc, char const *argv[])
{
    WaterPlane w;
    cout<<sizeof(w)<<endl;
    w.AirPlane::show();
    w.Ship::show();
    return 0;
}

(2)多继承的构造和析构

#include <iostream>
using namespace std;
class AirPlane
{
    protected:
        int high;
    public:
        AirPlane(int h):high(h)
        {
            cout<<"飞机的构造函数"<<endl;
        }
        ~AirPlane()
        {
            cout<<"飞机的析构函数"<<endl;
        }
};

class Ship
{
    protected:
        int speed;
    public:
        Ship(int s):speed(s)
        {
            cout<<"轮船的构造函数"<<endl;
        }
        ~Ship()
        {
            cout<<"轮船的析构函数"<<endl;
        }
};

class WaterPlane:public Ship,public AirPlane
{
    public:
        WaterPlane(int h,int s):AirPlane(h),Ship(s)
        {
            cout<<"水上飞机的构造函数"<<endl;
        }
        ~WaterPlane()
        {
            cout<<"水上飞机的析构函数"<<endl;
        }
};


int main(int argc, char const *argv[])
{
    WaterPlane w(100,40);
    return 0;
}

在这里插入图片描述
在这里插入图片描述

(3)多继承的二义性

#include <iostream>
using namespace std;
class TestA
{
    public:
        int a[7];
};

class TestB:public TestA
{
    public:
        int b;
};

class TestC:public TestA
{
    public:
        int c;
};

class TestD:public TestB,public TestC
{
    public:
        int d;
};
int main(int argc, char const *argv[])
{
    TestD td;
    cout<<sizeof(td)<<endl;
    //td.a;//会报错,不知道是哪个a
    return 0;
}

(4) 虚继承

虚继承的目的是为了让某个类作出声明,承若愿意共享它的基类,这个被共享的基类称为虚基类,在这种情况
下,无论虚基类在继承体系中出现多少次,在派生类中只会为其开辟一次内存空间

#include <iostream>
using namespace std;
class TestA
{
    public:
        int a;
};

class TestB:virtual public TestA
{
    public:
        int b;
};

class TestC:virtual public TestA
{
    public:
        int c;
};

class TestD:public TestB,public TestC
{
    public:
        int d;
};
int main(int argc, char const *argv[])
{
    TestB tb;
    cout<<sizeof(tb)<<endl;
    cout<<&tb<<endl;
    cout<<&tb.a<<endl;
    cout<<&tb.b<<endl;

    TestD td;
    cout<<sizeof(td)<<endl;
    cout<<&td<<endl;
    cout<<&td.a<<endl;
    cout<<&td.b<<endl;
    cout<<&td.c<<endl;
    cout<<&td.d<<endl;

    return 0;
}

二、多态

2.1 问题

#include <iostream>
using namespace std;
class Parent
{
    public:
        void show()
        {
            cout<<"this is Parent"<<endl;
        }
};
class Child:public Parent
{
    public:
        void show()
        {
            cout<<"this is child"<<endl;
        }
};
int main(int argc, char const *argv[])
{
    Parent *p1 = new Child;  //静态联编,编译器会p1的类型,调用parent里面的show函数
    p1->show();
    return 0;
}

2.2 多态的概念和使用

多态:多种形态,使用多态,当基类指针指向基类对象的时候,期待其按照基类的方法做事,当基类指针指向派生类对象的时候,就按照派生类的方法做事,实现同一个接口,多种方法,它有多种形态,这种现象称为多态。
多态的条件:
1.要有继承
2.要有虚函数重写(发生在不同的作用域,函数原型相同)
3.基类指针指向派生类对象
#include <iostream>
using namespace std;
class Parent
{
    public:
        virtual void show()
        {
            cout<<"this is Parent"<<endl;
        }
};
class Child:public Parent  //1.要有继承
{
    public:
        void show()    //2.要有虚函数重写
        {
            cout<<"this is child"<<endl;
        }
};
int main(int argc, char const *argv[])
{
    Parent *p1 = new Child;  //3.基类指针指向不同的对象
    p1->show();
    delete p1;
    p1 = new Parent;
    p1->show();
    delete p1;
    return 0;
}

2.3 多态的原理

#include <iostream>
using namespace std;
class Parent
{
    public:
        int a;
        virtual void show()
        {
            cout<<"this is Parent"<<endl;
        }
};
class Child:public Parent  //1.要有继承
{
    public:
        void show()    //2.要有虚函数重写
        {
            cout<<"this is child"<<endl;
        }
};
int main(int argc, char const *argv[])
{
    Parent p;
    Child c;
    cout<<sizeof(p)<<endl;
    cout<<sizeof(c)<<endl;
    cout<<"Parent的起始地址:"<<&p<<endl;
    cout<<"成员变量a的起始地址:"<<&p.a<<endl;
    return 0;
}

在这里插入图片描述

2.4 虚析构函数

根据析构的规则,只能从当前基类开始往上析构,而并不能调用到派生类中的析构函数,通过将基类的析构函数设置成虚函数,调用delete后,使其可以按照正确的顺序析构动态创建的对象。
#include <iostream>
using namespace std;
class Parent
{
    public:
        int a;
        virtual void show()
        {
            cout<<"this is Parent"<<endl;
        }
        Parent()
        {
            cout<<"Parent的构造函数"<<endl;
        }
        virtual ~Parent()
        {
            cout<<"Parent的析构函数"<<endl;
        }
};
class Child:public Parent  //1.要有继承
{
    public:
        void show()    //2.要有虚函数重写
        {
            cout<<"this is child"<<endl;
        }
        Child()
        {
            cout<<"Child的构造函数"<<endl;
        }
        ~Child()
        {
            cout<<"child的析构函数"<<endl;
        }
};
int main(int argc, char const *argv[])
{
    Parent *p = new Child;
    delete p;
    return 0;
}

2.5 动态类型识别

dynamic_cast
1.dynamic_cast是c++新型关键词
2.dynamic_cast用于基类和派生类之间的转换
3.dynamic_cast要求使用的目标类型是多态的。
   即要求所在类中至少有一个虚函数。
   用于指针转换时,转换失败会返回NULL指针。
   用于引用转换时,转换失败会引发bad_cast异常。
优势:
1.	不需要显示的声明和定义虚函数
2.  不用为每个类分配类型ID
缺点:
1.只能用于有虚函数的类
#include <iostream>
using namespace std;
class Parent
{
    private:
        int m_a;
    public:
        enum{ID = 0};
        virtual int GetId()
        {
            return ID;
        }
};
class Child:public Parent
{
    public:
        int array[102400];
        enum{ID = 1};
        virtual int GetId()
        {
            return ID;
        }
};
void func(Parent *p)
{
    //Child *c = (Child *)p;
    if(p->GetId() == Child::ID)
    {
        Child *c = (Child *)p;
        c->array[102400 -1] = 100;
        cout<<"转换成功"<<endl;
    }
    else
    {
        cout<<"转换失败"<<endl;
    }
    
}
int main(int argc, char const *argv[])
{
    Parent *p = new Child;
    //Parent *p = new Parent;
    func(p);
    return 0;
}

2.6 dynamic_cast

#include <iostream>
using namespace std;
class Parent
{
    private:
        int m_a;
    public:
        virtual void show(){}
};
class Child:public Parent
{
    public:
        int array[102400];
    public:
        virtual void show(){}
};
void func(Parent *p)
{
    Child *c  = dynamic_cast<Child *>(p);   //如果p指向的是基类对象,则转换失败,转换失败返回NULL
    if(NULL == c)
    {
        cout<<"转换失败"<<endl;
    }
    else
    {
        c->array[102400 -1] = 100;
        cout<<"转换成功"<<endl;
    }
}
int main(int argc, char const *argv[])
{
    Parent *p = new Child;
    //Parent *p = new Parent;
    func(p);
    return 0;
}

2.7 typeid

typeid可以用于获取一个表达式的类型信息
typeid的操作对象既可以是表达式,也可以是数据类型
	typeid(dataType);
或者:
	typeid(expression);
#include <iostream>
#include <typeinfo>
using namespace std;
class Parent
{
    private:
        int m_a;
    public:
        virtual void show(){}
};
class Child:public Parent
{
    public:
        int array[102400];
    public:
        virtual void show(){}
};
void func(Parent *p)
{
    if(typeid(*p) == typeid(Child))
    {
        Child *c = (Child *)p;
        c->array[102400 -1] = 100;
        cout<<"转换成功"<<endl;
    }
    else if(typeid(*p) == typeid(Parent))
    {
        cout<<"转换失败"<<endl;
    }
}
int main(int argc, char const *argv[])
{
    int a;
    char ch;
    Parent p1;
    Child c1;
    const type_info &pa = typeid(a);
    const type_info &pch = typeid(ch);
    const type_info &pp1 = typeid(p1);
    const type_info &pc1 = typeid(c1);
    cout<<pa.name()<<endl;
    cout<<pch.name()<<endl;
    cout<<pp1.name()<<endl;
    cout<<pc1.name()<<endl;
    Parent *p = new Child;
    //Parent *p = new Parent;
    func(p);
    return 0;
}

2.8 纯虚函数

virtual 返回值类型 函数名 (函数形参)= 0;
#include <iostream>
using namespace std;
class Parent   //含有纯虚函数的类称为抽象类,抽象类不能实例化对象
{
    public:
        virtual void show() = 0;  //纯虚函数,没有函数体
};
class Child:public Parent
{
    public:
        virtual void show()
        {
            cout<<"this is child"<<endl;
        }
};
int main(int argc, char const *argv[])
{
    Parent *p = new Child;
    p->show();
    return 0;
}
posted @ 2022-07-09 20:48  周末不下雨  阅读(18)  评论(0编辑  收藏  举报