C++ 虚函数 多态,以及销毁的时候的问题

一:C++ 虚函数定义

        在其他语言中实现多态的基础就是基类中存在抽象方法,然后子类去实现抽象方法从而实现了多态,但是在C++中实现多态遇到了一些问题,首先咱们先看一下虚函数的定义:

/*
	抽象基类
*/
class Creature {
private:
	string _skill;
public:
	string type;
	string name;
	int age;

	Creature() {
		cout << "a default creature is created.." << name << age << type << endl;
	};

	Creature(const string& t,const string& n,const int a): type(t),name(n),age(a) {
		cout << "creature was created" << endl;
		cout << "type of " << type << " creature was created and it's name is " << name << " age is " << age << endl;
	}

	~Creature() {
		cout << name << " creatrue was deleted" << endl;
	}
	/* 子类必须继承 纯虚函数不能指向子类对象 */
	virtual void eat() = 0;
};

上面的的存虚函数,子类必须实现这个方法

/* 子类必须继承 纯虚函数不能指向子类对象 */
virtual void eat() = 0;

子类中实现:

class Spider : public Creature {
public:
	float damage;

	Spider() {
		name = "spider";
		cout << "spider was created" << endl;
	}

	Spider(const string& t, const string& n, const int a, const float d) : Creature(t, n, a), damage(d) {
		cout << "spider's damage si " << damage << endl;
	}

	void eat() override {
		cout << "spider eating " << endl;
	}
};

eat()方法后面加入了 override表示重写了父类的方法

二: 多态的实现

        其他语言实现多态一般是 P p = new Son() 这种方式来使用,现在在C++语言种是不行的,只能通过指针和引用的方式才可以:

class Dog : public Creature {
public:

	Dog() {
		cout << "dog was created " << endl;
	}

	Dog(const string& t, const string n, const int a) : Creature(t, n, a) {
		
	}

	~Dog() {
		cout << name <<" dog was deleted " << endl;
	}

	void bark() {
		cout << "dog bark" << endl;
	}
	void eat() override {
		cout << "dog eating " << endl;
	}
};

void test() {
	Dog a("dog","w",4);
	// 堆上分配内存,函数调用结束后不会释放内存需要手动释放内存 造成一个问题就是只有Creature类的析构函数被调用了,但是子类的析构函数没有调用,
	Creature* creaturePtr = new Dog("dog", "wangcai", 5);

	delete creaturePtr;
}

int main() {
	/*Spider spider;
	* 
	* 
	Dog() 是在栈上分配内存,不需要程序员管理内存,对象被销毁的时候,析构函数会自动调用
	new Dog() 是在堆上分配内存
	Spider spider1("spider1","damageable",3,5.4);*/
	test();
	Creature* creaturePtr = new Dog("dog", "wangcai", 5);
	//delete creaturePtr;
}

但是我想到 Dog dog和 new Dog() 有什么区别呢,查过相关资料才得知,Dog dog的方式的话分配的内存空间是在栈上的,但是Creature* creaturePtr = new Dog(); 分配的空间是在堆上的,那么可以总结一下:

下面是一个表格,总结了Dog()new Dog()在C++中的主要区别:

特性Dog()new Dog()
内存分配栈(Stack)堆(Heap)
生命周期自动管理。当对象所在作用域结束时自动销毁。手动管理。需要显式使用delete来销毁。
访问方式直接通过对象访问。通过指针访问。
析构函数调用自动调用析构函数以释放资源。使用delete时自动调用析构函数释放资源。
适用场景当对象的使用期限限于一个狭窄的作用域内时。当对象需要跨多个作用域使用,或其生命周期不由单个作用域决定时。
资源释放自动。需要手动使用delete操作符。
风险无内存泄漏风险。如果忘记使用delete,可能会导致内存泄漏。

使用Dog()创建对象时,对象在栈上分配内存,并在其所在的作用域结束时自动销毁。这种方式简单且安全,但是它限制了对象的生命周期。

使用new Dog()创建对象时,对象在堆上分配内存,并且需要程序员显式地管理对象的生命周期,包括使用delete来销毁对象以释放资源。这种方式提供了更大的灵活性,但也增加了内存泄漏的风险,如果程序员忘记释放内存,

那么随之而来的还有一个问题就是如果 new Dog()的方式初始化对象的时候,delete操作能不能调用它的析构函数呢,所以才有了test()方法:

void test() {
	Dog a("dog","w",4);
	// 堆上分配内存,函数调用结束后不会释放内存需要手动释放内存 造成一个问题就是只有Creature类的析构函数被调用了,但是子类的析构函数没有调用,
	Creature* creaturePtr = new Dog("dog", "wangcai", 5);

	delete creaturePtr;
}

结果只有Creature类调用了析构函数,但是 new Dog指向对象没有销毁,容易造成内存泄漏

三:多态引入的内存泄漏怎么解决呢?

只需要修改一行代码:就是抽象基类的构造方法为虚函数

virtual ~Creature() {
	cout << name << " creatrue was deleted" << endl;
}

这样子类删除的时候,会首先调用Dog类的析构函数,再调用Creature类的析构函数。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值