嵌入式C++(四)

简介: 嵌入式C++(四)

一、继承


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


概念:类型兼容性原则是指在需要基类对象的地方,我们都可以直接使用公有派生类对象,通过公有继承,我

们可以得到基类中除了构造函数,析构函数外的所有成员,这样,凡是基类可以解决的问题,派生类都可以解

决。


(1)子类对象可以当成父类对象使用,子类对象是一种特殊的父类。

(2)父类指针可以直接指向子类对象

(3)父类引用可以直接引用派生类对象


0a2653c851af460fa595bd959398a8f1.png


#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;
}

0a2653c851af460fa595bd959398a8f1.png2d65d23f6d4748949b924e4057485923.png


(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;
}

0a2653c851af460fa595bd959398a8f1.png


(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;
}
相关文章
|
5月前
|
开发框架 Linux C语言
C、C++、boost、Qt在嵌入式系统开发中的使用
C、C++、boost、Qt在嵌入式系统开发中的使用
177 1
|
5月前
|
算法 Linux 程序员
嵌入式工程师以及C++程序员到公司就业需要掌握那些技术?
嵌入式工程师以及C++程序员到公司就业需要掌握那些技术?
|
5月前
|
数据处理 C++ UED
如何作为一个嵌入式软件工程师博主获得铁粉:C/C++ 技术分享之道
如何作为一个嵌入式软件工程师博主获得铁粉:C/C++ 技术分享之道
111 0
|
5月前
|
C语言 数据安全/隐私保护 C++
嵌入式中如何把C++代码改写成C语言代码
嵌入式中如何把C++代码改写成C语言代码
64 0
|
5月前
|
存储 缓存 Java
嵌入式系统中C++内存管理基本方法
嵌入式系统中C++内存管理基本方法
128 0
|
5月前
|
存储 编译器 程序员
嵌入式系统中C++基础知识精髓
嵌入式系统中C++基础知识精髓
103 0
|
5月前
|
关系型数据库 数据库 C++
嵌入式数据库sqlite3【基础篇】基本命令操作,小白一看就懂(C/C++)
嵌入式数据库sqlite3【基础篇】基本命令操作,小白一看就懂(C/C++)
|
5月前
|
存储 编译器 C++
嵌入式中C++ 编程习惯与编程要点分析
嵌入式中C++ 编程习惯与编程要点分析
50 1
|
5月前
|
架构师 数据挖掘 程序员
嵌入式系统中C++ 类的设计和实现分析
嵌入式系统中C++ 类的设计和实现分析
64 1
|
5月前
|
算法 小程序 编译器
嵌入式中C++开发的基本操作方法
嵌入式中C++开发的基本操作方法
56 0