c++继承中的构造函数与析构函数

本文探讨C++中的继承特性,强调其在代码复用和功能拓展中的作用。介绍了构造函数用于对象初始化,析构函数在对象销毁时自动调用。派生类的构造函数需要为基类构造函数提供初始化参数,确保基类对象的正确创建。并通过示例说明了构造函数和继承顺序对程序输出的影响。

太久没有温习的知识,今天捡起来复习一下

首先是基类的定义

class baseClass{
private:
//private member
protected:
//protected member
public:
//public member
};
其实基类的定义跟我们平时写的类的定义完全一样,不过是在继承中,多了基类这一重身份而已

现在来说一下c++为什么要增加 继承这一个特性

面向对象编程的一个特点就是代码的可重用性,使用经过测试后的代码,比自己重新设计,然后写的代码更安全也更省事儿,很多情况,我们的手头会有一些已经写好的类库,怎么样才能更快的做一些功能上的拓展了,没错,那就是继承了

继承,也就是继承基类的成员和方法,同时派生类可以设置自己的成员函数和成员变量,对于程序员来说,就很方便使用原有的功能,并且在这个功能上进行拓展

举个例子,如果你继承了一笔财产去做生意,肯定比你白手起家更容易成功, 所以继承是c++的一个重要特性之一

派生类的定义如下:

class derivedClass:public baseClass1, public baseClass2......{
private:
//private member
protected:
//protected member
public:
//public member
};
派生类的定义与一般类不同的地方要显示的声明继承的类的列表,也就是derivedClass后面的一串类的列表

现在开始说构造函数与析构函数

首先说说构造函数,c++中的类封装了成员变量和成员函数,但是在有的情况下,这些成员变量是不应该暴露给其他人的,也就是对于其他类来说,这些变量是不可见的,那么怎么样声明这些变量呢,那就需要依靠构造函数啦

构造函数功能就是在对象创建时,初始化对象,为对象的一些成员变量赋值

一个类可以有多个构造函数,构造函数的分类可以有以下几种

mClass::mClass(){
	//这是默认构造函数,参数列表为空
}

mClass::mClass(type arg1, type arg2,......){
	//这是一般构造函数,传入的参数用来初始化对象
}

mClass::mClass(const mClass&){
	//这是拷贝构造函数,传入的参数是mClass类的一个实例化对象
}
说完了构造函数再说一下析构函数

既然构造函数是对象创建时自动调用的函数,那很容易知道,析构函数就是对象被销毁(释放内存)时,自动调用的函数

不过这里要注意的是,析构函数只有一种形式

mClass:~mClass(){
//content
}
通常来说,由编译器决定在什么时候调用析构函数,并且析构函数不会在代码中被显示的调用
如果创建的对象时静态类型(即创建时加上了static修饰符),那么对象要等到整个程序运行完 才被释放,也就是说,析构函数在程序结束时才被调用;如果创建的是自动存储类型(默认声明都是自动存储类型),那么在相应的block结束时,对象就会被释放,此时,析构函数被调用

另外,如果对象是通过new运算符创建的,那么delete掉这个对象时,析构函数也会被调用

现在来说一下派生类的构造函数,派生类的构造函数与一般类的构造函数略有不同的是,派生类的构造函数要为基类的构造函数提供初始化参数

这样说可能比较复杂了,简单的来说,如果我要使用一个派生类对基类进行功能上的拓展,那么我肯定要先创建一个基类的对象,这样才能使用它提供的方法,然后再创建我们的派生类对象,所以,在派生类的构造函数时,会先初始化基类,得到一个基类的对象,然后再初始化派生类,下面是我自己写的一个demo

#include<iostream>
using namespace std;

class animal{
	private:
		int weight;
	public:
		animal(){
			weight = 0;
			cout << "in the default constructor of the animal" << endl;
		}

		animal(int _weight){
			weight = _weight;
			cout << "in the constructor of the animal" << endl;
		}

		~animal(){
			cout << "in the destructor of the animal" << endl;
		}

};

class catamount{
private:
	int weight;
public:
	catamount(){
		weight = 0;
		cout << "in the default constructor of the catamout" << endl;
	}

	catamount(int _weight){
		weight = _weight;
		cout << "in the constructor of the catamount" << endl;
	}

	~catamount(){
		cout << "in the destructor of the catamount" << endl;
	}
};

class tiger:public catamount, public animal{
private:
	int weight;
public:
	tiger():catamount(),animal(){
		weight = 0;
		cout << "in the default constructor of the tiger" << endl;
	}
	tiger(int weight1, int weight2, int weight3):catamount(weight2), animal(weight3){
		cout << "in the constructor of the tiger" << endl;
		weight = weight3;
	}
	~tiger(){
		cout << "in the destructor of the tiger" << endl;
	}
};


int main(){
	tiger mTiger(60, 60, 60);
	return 0;
}
tiger类同时继承了catamount类和animal类,所以再创建它时,会调用到它的两个父类catamount和animal,下面看一下输出

in the constructor of the catamount
in the constructor of the animal
in the constructor of the tiger
in the destructor of the tiger
in the destructor of the animal
in the destructor of the catamount
可以看到,创建一个派生类对象时,会先调用基类的构造函数,而程序准备销毁对象时,则会先调用派生类的析构函数

如果将继承列表中的类交换一下位置,也就是吧animal和catamount的位置换一换(注意,构造函数那块儿也要换位置,这是跟继承先后顺序相对应的),那么输出就变成这样了

in the constructor of the animal
in the constructor of the catamount
in the constructor of the tiger
in the destructor of the tiger
in the destructor of the catamount
in the destructor of the animal
所以,一个类在继承多个类时,继承的先后顺序是很重要的,这会影响析构函数和构造函数调用的先后顺序






评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值