【C/C++】【类和对象】基类和派生类

派生类对象模型

子类对象包含多个组成部分(也就是多个子对象);

  1. 含有派生类自己定义的成员变量、成员函数的子对象;
  2. 该派生类所继承的基类的子对象,这个子对象包含的是基类中定义的成员变量、成员函数(派生类对象含有基类对应的组成部分);
  • 两部分数据在内存中的存储可能不连续;
  • 基类指针可以new派生类对象,因为派生类对象含有基类部分,所以我们可以把派生类对象当成基类对象来用;编译器内部做了隐式的派生类到基类的转换;这种转换的好处是有些需要用到基类引用/指针地方,可以用这个派生类对象的引用/指针来代替;

派生类构造函数

  • 派生类实际使用基类的构造函数来初始化它的基类部分;基类控制基类部分的成员初始化,派生类控制派生类部分成员的初始化;
  • 定义一个派生类对象的时候,既调用基类构造函数,有调用派生类构造函数;
  • 传递参数给基类构造函数问题:通过派生类的构造函数初始化列表;
#include <iostream>
using namespace std;
class Father
{
public:
    Father(int i):m_values(i)
    {
        cout << "Father(int i)" << endl;
    }
    virtual ~Father()
    {
        cout << "~Father()" << endl;
    }
private:
    int m_values;
};
class Son : public Father
{
public:
    //通过子类的初始化列表给父类构造函数传参
    Son(int i, int k):Father(i), m_value_b(k)
    {
        cout << "Son(int i, int k)" << endl;
    }
    ~Son()
    {
        cout << "~Son()" << endl;
    }
public:
    int m_value_b;
};
int main()
{
    //构造函数:先基类再子类
    //析构函数:先子类再基类
    Son* b = new Son(1, 2);
    delete b;

    return 0;
}

既当父类又当子类

  1. Base
  2. Father: Base是Father的直接基类
  3. Son:Base是Sone的间接基类
    继承关系一直传递,构成了一种继承链,最终的结果是Son会包含它的直接基类的成员以及每个间接基类的成员
    Father这个类就是既当父类又当子类;
#include <iostream>
using namespace std;
class Base
{
public:
    Base() 
    {
        cout << "Base()" << endl;
    };
    ~Base() 
    {
        cout << "~Base()" << endl;
    };
};
class Father: public Base
{
public:
    Father(int i):m_values(i)
    {
        cout << "Father(int i)" << endl;
    }
    virtual ~Father()
    {
        cout << "~Father()" << endl;
    }
private:
    int m_values;
};
class Son : public Father
{
public:
    //通过子类的初始化列表给父类构造函数传参
    Son(int i, int k):Father(i), m_value_b(k)
    {
        cout << "Son(int i, int k)" << endl;
    }
    ~Son()
    {
        cout << "~Son()" << endl;
    }
public:
    int m_value_b;
};

int main()
{
    Son* son = new Son(1, 2);
    delete son;
    return 0;
}

不想当基类的类

final:C++11中引入,加到基类后面,使其无法被继承;

class Base final
{
public:
    Base() 
    {
        cout << "Base()" << endl;
    };
    ~Base() 
    {
        cout << "~Base()" << endl;
    };
};
class Father
//class Father : public Base 错误
{
public:
    Father(int i):m_values(i)
    {
        cout << "Father(int i)" << endl;
    }
    virtual ~Father()
    {
        cout << "~Father()" << endl;
    }
private:
    int m_values;
};

静态类型和动态类型

  • 静态类型:变量声明的时候的类型,静态类型编译的时候类型是已知的;
  • 动态类型:这个指针/引用所代表的的内存中的对象的类型;运行的时候才知道类型;
  • 动态类型和静态类型;只有基类指针/引用才存在静态类型和动态类型不一致的情况;如果不是基类指针/引用,其动态类型和静态类型永远是一致的;

派生类向基类的隐式类型转换

基类对象能独立存在,也能作为派生类对象的一部分存在

Father* father = new Son(); //积累指针指向一个派生类对象 
Father& q = *father;    //基类引用绑定到派生类对象
Son son;
Father* father = &son; //可以
Son* p_son = father; // 非法,编译器通过静态类型推断转换合法性,发现基类不能转成派生类;如果基类中有虚函数,可以通过dynamic_cast转换;
Son* p_son = dynamic_cast<Son*> father;

并不存在从基类到派生类的自动类型转换

Son* son = new Father(); //非法       

Father father;
Son &son = father; //非法,不能将基类转换成派生类,派生类的引用不能绑定到基类对象上
Son &son = &father; //非法,不能讲基类转成派生类,派生类指针不能指向基类地址

父类子类之间的拷贝和赋值

用派生类对象为一个基类对象初始化或者赋值的时候,只有该派生类对象的基类部分会被拷贝或者复制,派生类部分将被忽略掉;

Son son; //派生类对象;
Father father(son); //用派生类对象来定义并初始化基类对象,这个会导致基类的拷贝构造函数的执行

原文链接: https://www.cnblogs.com/NaughtyCoder/p/13343854.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    【C/C++】【类和对象】基类和派生类

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/369128

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 下午6:47
下一篇 2023年3月2日 下午6:47

相关推荐