46.继承中的构造和析构

本文详细解析了C++中子类构造和析构的过程,包括如何调用父类构造函数,以及构造和析构的顺序。通过具体代码示例,展示了在不同情况下子类如何正确地初始化和清理资源。

继承中的构造和析构

  • 子类对象在创建时会首先调用父类的构造函数
  • 父类构造函数执行完毕后,才会调用子类的构造函数
  • 当父类构造函数有参数时,需要在子类初始化列表(参数列表)中显示调用父类构造函数
  • 析构函数调用顺序和构造函数相反    

                      

继承与组合混搭的构造和析构

                      

子类创建对象时,先调用父类的构造,然后调用自身构造
析构顺序与构造顺序相反
子类是不会继承父类的构造函数和析构函数
补充内容,如果父类中没有合适默认构造,那么子类可以利用初始化列表的方式显示的调用父类的其他构造

main.cpp

// 40.继承方式.cpp : 定义控制台应用程序的入口点。
//

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

class Base
{
public:
	Base()
	{
		m_A = 10;
		cout << "Base默认构造函数调用" << endl;
	}
	~Base()
	{
		cout << "Base的析构函数调用" << endl;
	}

	int m_A;
};
// 子类会继承父类的成员属性,成员函数
//但是 子类 不会继承 父类 构造函数 和 析构函数
//只有父类自己知道如果构造和析构自己的属性,而子类不知道


class Son :public Base
{
public:
	Son()
	{
		cout << "Son默认构造函数调用" << endl;
	}
	~Son()
	{
		cout << "Son的析构函数调用" << endl;
	}
};

void test01()
{
	//Base b1;
	/*输出
	Base默认构造函数调用
	Base的析构函数调用
	*/
	Son s1;
	/*输出
	Base默认构造函数调用
	Son默认构造函数调用
	Son的析构函数调用
	Base的析构函数调用
	*/
}



class Base2
{
public:
	Base2(int a)
	{
		this->m_A = a;
		cout << "有参构造函数调用" << endl;
	}
	int m_A;
};

class Son2 :public Base2
{
public:
	Son2(int a) : Base2(a)//利用初始化列表方式 显示调用 有参构造
	{
	}
};

void test02()
{
	Son2 s2(1000);
	/*输出
	有参构造函数调用
	*/
}


int main(){

	test02();

	system("pause");
	return EXIT_SUCCESS;
}

 

### 类的构造函数种类 C++类的构造函数主要有以下几种类型: 1. **默认构造函数**:没有参数或所有参数都有默认值的构造函数。如果用户没有显式定义任何构造函数,编译器会自动生成一个默认构造函数[^2]。 2. **带参数的构造函数**:用于根据传入的参数初始化对象的状态。 3. **拷贝构造函数(复制构造函数)**:用于创建一个新对象作为已有对象的副本。其形式通常为 `ClassName(const ClassName&)`。如果用户未显式定义,编译器也会提供一个默认的实现,该实现执行浅拷贝操作[^1]。 --- ### 深拷贝与浅拷贝的区别 - **浅拷贝**:当使用默认的拷贝构造函数或赋值运算符时,进行的是逐字节的拷贝。对于指针成员变量来说,这种拷贝方式会导致两个对象指向同一块内存区域,从而可能引发双重释放等问题[^1]。 - **深拷贝**:通过显式地为每个指针成员分配新的内存空间,并将原对象的数据复制到新的内存中,确保两个对象拥有独立的数据副本,互不影响。通常需要用户自己实现拷贝构造函数赋值运算符重载来完成深拷贝[^1]。 --- ### 构造函数与函数的基本概念 - **构造函数**:构造函数是一个特殊的成员函数,其名称与类名相同,没有返回类型(即使是void也不行)。它在创建对象时自动调用,用于初始化对象的成员变量,为对象分配资源并执行必要的初始化操作[^2]。 - **函数**:函数也是一个特殊的成员函数,其名称是在类名前加一个波浪号~,也没有返回类型。它在对象销毁时自动调用,主要用于释放对象占用的资源,如关闭文件、释放动态分配的内存等。 --- ### 函数能否重载 函数不能被重载。因为函数没有参数列表,所以无法通过改变参数的方式来实现重载。每个类只能有一个函数[^1]。 --- ### 继承中子类父类的构造顺序 在继承关系中,构造函数函数的执行顺序遵循如下规则: - **构造顺序**:先调用基类的构造函数,然后按照声明顺序依次调用派生类中的成员对象的构造函数,最后执行派生类自身的构造函数体。 - **顺序**:过程是构造过程的逆序。首先执行派生类的函数体,接着按相反于构造顺序的方式调用成员对象的函数,最后调用基类的函数[^1]。 --- ### 类的静态成员作用及初始化方式 - **静态成员的作用**:静态成员属于整个类而不是类的具体实例。这意味着无论创建多少个类的对象,静态成员都只有一份拷贝,所有对象共享这个静态成员。 - **静态成员的初始化**: - 对于整型常量静态成员,可以直接在类内声明时初始化。 - 其他类型的静态成员必须在类外单独初始化。 - 静态成员可以通过类名直接访问,也可以通过对象访问。 --- ### 继承的方式及其区别 C++支持三种继承方式: 1. **公有继承(public inheritance)**:基类的public成员在派生类中保持public;protected成员保持protected;private成员不可访问。 2. **保护继承(protected inheritance)**:基类的publicprotected成员在派生类中都成为protected;private成员不可访问。 3. **私有继承(private inheritance)**:基类的所有成员在派生类中都变为private;private成员仍然不可访问[^1]。 --- ### C++中重载、重写、重定义绑定机制的区别 - **重载(Overloading)**:发生在同一个作用域内,函数名相同但参数列表不同的一组函数称为重载函数。重载函数的返回类型可以不同,但这不是区分重载函数的标准[^2]。 - **重写(Overriding)**:也叫覆盖,发生在派生类与基类之间,要求函数名、参数列表以及返回类型完全一致。只有虚函数才能被重写,且基类中的函数必须是virtual[^2]。 - **重定义(Redefinition)**:同样出现在派生类与基类之间,但是不要求函数签名完全一致。如果基类函数不是虚函数,则派生类中的同名函数只是隐藏了基类版本,并非真正的重写[^2]。 - **绑定机制**: - **静态绑定(Static Binding)**:又称早期绑定,指的是在编译阶段确定调用哪个函数的过程。普通函数调用非虚函数的调用采用静态绑定。 - **动态绑定(Dynamic Binding)**:又称晚期绑定,是指在运行时根据对象的实际类型决定调用哪个虚函数的过程。这是多态性的基础。 --- ```cpp // 示例代码展示默认构造函数、带参数构造函数拷贝构造函数 class MyClass { public: int value; // 默认构造函数 MyClass() : value(0) {} // 带参数的构造函数 MyClass(int val) : value(val) {} // 拷贝构造函数 MyClass(const MyClass& other) : value(other.value) {} }; ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值