C++入门笔记--继承机制中的构造器和析构器

正如前面的博客里写的,C++支持程序员写出在创建或者销毁一个对象时自动调用的方法,也就是构造器和析构器。在没有继承机制的情况下,我们很容易理解这些方法在创建或销毁一个对象的时候被调用,但是一旦使用了继承机制,构造器和析构器就变得有点复杂了。

构造器

比如有个基类Animal(),他将在创建子类Pig类型的对象的时候最先被调用,如果Pig类也有一个构造器,他将排在第二个被调用,因为有一个原则:基类必须在子类之前初始化。

然后继续讨论:如果构造器带着输入参数,事情就变得稍微有点复杂。正确做法如下:


class Animal{
public:
	std::string name;
	Animal(std::string theName);
};

class Pig:public Animal{
	Pig(std::string theName);
};

Animal::Animal(std::string theName){
	this->name = theName;
}

Pig::Pig(std::string theName):Animal(theName){
	
}

注意在子类的构造器定义里的“Animal(theName)”的语法含义是:

当调用Pig()构造器的时候(以theName作为输入参数),Animal()构造器也将被调用(theName输入参数将传递给他)

于是,当我们使用Pig pig("小香猪")的时候,将把字符串“小香猪”传递给Pig()和Animal(),赋值动作实际发生在Animal()方法里,Pig()的构造器是空的,他继承的是Animal()的构造器。

下面就结合上一个博客里面的东西来写一下继承机制下的构造器,注意下面代码里pig类和turtle类的构造器是如何继承animal类的。

#include<iostream>
#include<string>

class Animal{//类名 
public:
	std::string name;
	std::string mouth;
	 
	void eat();
	void sleep(); 
	Animal(std::string theName);
};

class Pig:public Animal{
public:
	void climb();
	Pig(std::string theName);
};

class Turtle:public Animal{
public:
	void swim();
	Turtle(std::string theName);
};

Animal::Animal(std::string theName){
	this->name = theName;
}

Pig::Pig(std::string theName):Animal(theName){	
}

Turtle::Turtle(std::string theName):Animal(theName){
}

void Animal::eat(){
	std::cout<<"I'm eating!\n"<<std::endl;
}

void Animal::sleep(){
	std::cout<<"I'm sleeping!Don't disturb me!\n"<<std::endl;
}

void Pig::climb(){
	std::cout<<"I can climb the tree!\n"<<std::endl;
}

void Turtle::swim(){
	std::cout<<"I can swim!\n"<<std::endl;
}

int main(){
	Pig pig("小香猪");
	Turtle turtle("小甲鱼");
	
	std::cout<<"我是一只猪,我的名字叫"<<pig.name<<std::endl;
	std::cout<<"每只乌龟都有一个伟大的名字"<<turtle.name<<std::endl; 
	
	pig.eat();
	turtle.eat();
	
	pig.climb();
	turtle.swim();
	
	return 0;
}

结果如图: 

 析构器

在销毁某个对象的时候,基类的析构器也将被自动调用,但是这些事情编译器会自动替你处理。因为析构器不需要输入参数,所以根本用不着使用:SuperClassMethod(arguments)语法。与构造器的情况相反,基类的析构器将在子类的最后一条语句执行完毕后才被调用。

因为在销毁对象时,编译器会帮我们做很多工作,所以我们这一部分就跳过,但是要明白继承的机制在构造器和析构器里是如何体现的,读下面这段代码,写出输出内容,答案放在最后,看是否已经对这个概念有了进一步的掌握。

#include<iostream>
#include<string>

class BaseClass{
public:
	
	BaseClass();
	~BaseClass();
	
	void doSomething();
};

class SubClass:public BaseClass{
public:
	SubClass();
	~SubClass();
};

BaseClass::BaseClass(){
	std::cout<<"进入基类构造器....."<<std::endl;
	std::cout<<"我在基类构造器里做了一些事...\n"<<std::endl;	
}

BaseClass::~BaseClass(){
	std::cout<<"\n进入基类析构器....."<<std::endl;
	std::cout<<"我在基类析构器里也做了一些事...\n"<<std::endl;	
}

void BaseClass::doSomething(){
	std::cout<<"\n我做了一些事!\n";	
}

SubClass::SubClass(){
	std::cout<<"进入子类构造器....."<<std::endl;
	std::cout<<"我在子类构造器里做了一些事...\n"<<std::endl;	
}

SubClass::~SubClass(){
	std::cout<<"进入子类析构器....."<<std::endl;
	std::cout<<"我在子类析构器里也做了一些事..."<<std::endl;	
}

int main(){
	SubClass subclass;
	subclass.doSomething();
	std::cout<<"OK!我执行完了 要收工了 执行main的return啦~~~\n\n";
	return 0;
} 

 结果:

 解析:

 其实继承就相当于一个嵌套,父类把子类给嵌套起来,自然先执行父类的构造函数,然后子类的构造函数,然后执行main里调用的函数doSomething(),然后继续执行main函数的下一条语句“OK.......”,析构函数是在执行main的返回值那一行的时候调用的,在那个时候,程序关闭,已经创建的对象要将她销毁,所以调用析构函数,但是先调用子类的析构函数,再调用父类的析构函数。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值