派生类对象模型
子类对象包含多个组成部分(也就是多个子对象);
- 含有派生类自己定义的成员变量、成员函数的子对象;
- 该派生类所继承的基类的子对象,这个子对象包含的是基类中定义的成员变量、成员函数(派生类对象含有基类对应的组成部分);
- 两部分数据在内存中的存储可能不连续;
- 基类指针可以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;
}
既当父类又当子类
- Base
- Father: Base是Father的直接基类
- 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大佬
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/369128
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!