本文已参与「新人创作礼」活动,一起开启掘金创作之路。
游戏开发之继承中的构造函数、析构函数及继承中的常见问题解决方案(C++基础)
1.继承中的类对象模型
在C++编译器中,可以将派生类内部理解为结构体,是由基类成员叠加子类新成员及以某种方式关联成员函数形成的结构体。
2.对象构造函数和析构函数的调用原则
- 子类(派生类)对象在创建时,会先调用父类(基类)的构造函数。
- 父类(基类)构造函数执行后,才会调用子类(派生类)的构造函数(如果有多个父类,按照继承的顺序执行父类构造函数)。
- 父类构造函数有参数时,需要在子类构造函数的初始化列表中显式调用父类的构造函数。
- 析构函数的调用顺序和构造函数的调用顺序相反(符合栈区,入栈出栈的数据结构,依次创建及释放)。
3.继承中出现同类成员的处理方法
- 当子类(派生类)成员和父类(基类)成员同名时,子类依然从父类继承同名的成员,通过:类名 作用域符 成员,进行访问。
// 调用指定类的成员
// 类变量名.类名::成员变量
// 类变量名.类名::成员函数
// 类变量名->类名::成员变量
// 类变量名->类名::成员函数
- 如果子类成员和父类同名,子类访问其成员默认访问子类的成员(本作用域,符合就近原则)。
- 在子类通过作用域::进行同名成员区分访问(在派生类中使用基类的同名成员,显式使用:类名::成员,进行访问)。
4.不是所有的基类成员函数都会被继承
不会被子类继承的成员函数:
- 构造函数
- 析构函数
- operator=
在继承的过程中,如果没有创建这些函数,编译器会自动在派生类生成它们。
5.实例
//默认情况下,基类的构造函数不被继承,派生类需要定义自己的构造函数。
//C++11规定,可用using语句继承基类构造函数;语法形式:using Base::Base;
class A
{
public:
int a;
A(int a)
{
this->a = a;
//__FUNCTION__,C++内置宏,打印执行的函数名称
//__LINE__,C++内置宏,打印该行代码行数
std::cout << __FUNCTION__ << " " << __LINE__ << std::endl;
}
~A()
{
std::cout << __FUNCTION__ << " " << __LINE__ << std::endl;
}
void Print()
{
std::cout << __FUNCTION__ << " " << __LINE__ << std::endl;
}
};
class B :public A
{
//继承父类A的构造函数
using A::A;
public:
int b;
//在子类构造函数的初始化列表中显式调用父类的构造函数
B(int b) :A(6)
{
this->b = b;
std::cout << __FUNCTION__ << " " << __LINE__ << std::endl;
}
~B()
{
std::cout << __FUNCTION__ << " " << __LINE__ << std::endl;
}
void Print()
{
std::cout << __FUNCTION__ << " " << __LINE__ << std::endl;
}
};
class C :public B
{
public:
int b;
//在子类构造函数的初始化列表中显式调用父类的构造函数
C() :B(2)
{
this->b = 1;
std::cout << __FUNCTION__ << " " << __LINE__ << std::endl;
}
~C()
{
std::cout << this->b << " " << B::b << " " << B::A::a << std::endl;
std::cout << __FUNCTION__ << " " << __LINE__ << std::endl;
}
void Print()
{
std::cout << __FUNCTION__ << " " << __LINE__ << std::endl;
}
};
int main()
{
//查看A、B、C类的大小可以看出继承中的类对象模型
std::cout << "A size:" << sizeof(A) << std::endl;
std::cout << "B size:" << sizeof(B) << std::endl;
std::cout << "C size:" << sizeof(C) << std::endl;
//可以看出继承中构造函数和析构函数的调用原则
//以及继承中出现同类成员的处理方法
C c;
c.Print();
c.B::Print();
c.A::Print();
//派生类和基类的类型转换,派生类可以转换为基类,基类无法转换为派生类
/*
公有派生类对象可以被当作基类的对象使用,反之则不可。
派生类的对象可以隐式转换为基类对象;
派生类的对象可以初始化基类的引用;
派生类的指针可以隐式转换为基类的指针。
*/
B *b = &c;
//就近原则(本作用域内),打印B的Print
b->Print();
return 0;
}
版本声明:本文为CSDN博主[ufgnix0802]的原创文章。
原文链接:(blog.csdn.net/qq135595696…)