构造函数和析构函数

c++要将类像初始化基本类型一样使用类。然而我们前面介绍过C语言中的结构体,但是类没有办法像结构体一样的初始化 因为结构体的数据成员都是公开的,而类是私有的,因此,只有合适的成员函数,可以将类初始化。一般来说,最好在创建对象时进行初始化。C++提供了一个特殊的成员函数,用于构造新对象,将值赋给数据成员。C++提供声明,又程序员来定义。

声明和定义构造函数

由于本类中有三个数据成员,如果要设置commpany成员,将其他成员设置为0

Stock(const string &co,long n = 0,double pr  0.0);
//定义可以这样写
Stock::Stock(const string &co,long n,double pr)
{
	company = co;
	if (n < 0)
	{
		std::cout << "Number of shares can't be negative;"
			<< "company " << "share set to 0.\n";
		share = 0;
	}
	else
	{
		share = n;
		share_val = pr;
		set_tot();
	}
}

上述代码和成员函数acquire()相同,区别是,程序声明对象时,将自动调用构造函数。
需要注意的是,构造函数的参数名不可与类成员名称一样,否则会导致混乱。为了避免混乱,常见的作法是在数据成员名中使用m_前缀

class Stock
{
private:
string m_commpany;
long m_shares;
}

也可以加后缀_

使用构造函数

  1. 显式调用构造函数
    Stock food = Stock(“World Cabbage”,250,1.25);
    这样就初始化food对象的成员
  2. 隐式调用构造函数
    Stock garment(“Furry Mason”,50,2.5);
    显式调用等价于隐式调用
    每次创建类对象,C++都使用类构造函数。
    Stock *pstock = new Stock(“Bill”,18,19.0);
    这条语句创建了一个Stock对象,并将其初始化为参数提供的值,并将该对象的地址赋给pstock指针,在这种情况下,虽然对象没有名称,但可以用指针管理该对象。需要注意的是,不同于类方法的是,构造函数由类调用,无法使用对象调用,因为用构造函数初始化对象之前,对象是不存在的。

默认构造函数

默认构造函数是未提供显式初始值时,用来创建对象的构函数,例如
Stock s1;默认构造函数不会进行任何操作

Stock::Stock();

只创建对象,并不进行初始化,默认构造函数也没有参数。编译器只有在没有定义任何构造函数时,才会提供默认构造函数。为类定义了构造函数后,我们就必须提供默认构造函数,如果只提供了非默认构造函数而没有提供默认构造函数

Stock s1;//这种调用默认构造函数将会出错

如果要创建对象且不显式地初始化,则必须定义一个不接受任何参数的默认构造函数,定义默认构造函数的方式有两种

  1. 给定构造函数所有参数提供默认值
    Stcok(const string &co = “error”,int n = 0,double pr = 0.0);
  2. 通过函数重载定义另一个构造函数
    Stock();
    实际上,默认构造函数应为所有成员提供初始值
Stock::Stock()
{
commpany = "no name";
share = 0;
share_val = 0.0;
total_val = 0.0;
}

在设计类时,应提供对所有类成员坐隐式初始化的默认构造函数。
然后就可以进行例如
Stock first;
Stock first = Stock();
Stock*first = new Stock;

析构函数

用构造函数创建对象,对应的需要有一个函数做清理工作,这个函数叫析构函数
如果构造函数使用new来分配内存,则析构函数将使用delete清理这些使用完的内存,如果构造函数没有new,那么析构函数也不需要其他操作

Stock::~Stock();

与构造函数不同的是,析构函数是没有参数的,所以它的原型只能是上面这种情况。什么时候会调用析构函数呢,如果是静态存储类对象,析构函数将会在程序结束后自动调用,如果是new出来的,则当delete时候,会调用析构函数,所以程序必须提供一个析构函数,编译器将隐式地声明一个默认析构函数。
我们可以根据我们学习的函数修改一下我们之前写的代码

//stock.h
#pragma once
#include<string>
#ifndef  _STOCK_H
#define _STOCK_H
class Stock
{
private:

	std::string company;
	long share;
	double share_val;
	double total_val;
	void set_tot() { total_val = share_val * share; }
public:
	Stock();
	~Stock();
	Stock(const std::string& co, long n, double pr);
	void buy(long num, double price);
	void sell(long num, double price);
	void update(double price);
	void show();
};
#endif // ! _STOCK_H

//stcok.cpp
#include<iostream>
#include"stcok.h"
Stock::Stock()
{
	std::cout << "Default cibstructor called\n";
	company = "no name";
	share = 0;
	share_val = 0.0;
	total_val = 0.0;
}
 Stock::Stock(const std::string& co, long n, double pr)
{
	std::cout << "Constructor using " << co << " called\n";
	company = co;
	if (n < 0)
	{
		std::cout << "Number of shares can't be negative;"
			<< "company " << "share set to 0.\n";
		share = 0;
	}
	else
	{
		share = n;
		share_val = pr;
		set_tot();
	}
}
 Stock::~Stock()
 {
	 std::cout << "bye, " << company << "!\n";

 }
void Stock::buy(long num, double price)
{
	if (num < 0)
	{
		std::cout << "Number of shares purchased can't be negative."
			<< "Transcation is aborted.\n";
	}
	else
	{
		share += num;
		share_val = price;
		set_tot();
	}
}
void Stock::sell(long num, double price)
{
	using std::cout;
	if (num < 0)
	{
		cout << "Number if shares sold can't be negative. "
			<< "Transcation is aborted.\n";
	}
	else if (num>share)
	{
		cout << "You can't sell more than you have"
			<< "Transcation is aborted.\n";
	}
	else
	{
		share -= num;
		share_val = price;
		set_tot();
	}
}
void Stock::update(double price)
{
	share_val = price;
	set_tot();
}
void Stock::show()
{
	std::cout << "Company: " << company
		<< "Share: " << share << '\n'
		<< "share price: $" << share_val
		<< "Total Worth: $" << total_val << '\n';
}

//main.cpp
#include<iostream>
#include"stcok.h"
int main()
{
	using std::cout;
	cout << "Using constructors to create new objects\n";
	Stock s1("NanoSmart",12,20.0);
	s1.show();
	Stock s2 = Stock("Boffo Objects", 2, 2.0);
	s2.show();
	cout << "Assigning stock1 to stcok2:\n";
	//s1.buy(15, 18.125);
	//s1.show();
	s2 = s1;
	cout << "Listing stock1 and stock2:\n";
	s1.show();
	s2.show();
	cout << "Using a constructor to reset an object\n";

	s1 = Stock("Nifty Foods", 10, 50.0);
	cout << "Revised s1:\n";
	s1.show();
	cout << " Done\n";
 
	return 0;

}

输出结果:
image.png

说明一下代码
首先用两种方式分别创建了s1和s2俩个对象,第一种通过构造函数初始化对象,第二种,先调用构造函数创建一个临时对象并初始化然后赋值给s2,将一个对象赋给同类型的另一个对象时,C++将源对象的每个数据成员的内容复制到目标对象对应的数据成员中。
构造函数不仅仅可以初始化新对象,还可以给已存在的对象重新赋值,和上面第二种是一样的。main函数调用完之后,会调用析构函数,因为是存储在栈中的对象,所以先进后出,先清理后创建的对象。
我们尽量使用不产生临时对象的方式来初始化对象,会增加程序的效率

网站标题:CV鼻祖洋芋

原创文章,作者:locus,如若转载,请注明出处:https://blog.cvpotato.cn/forward-code/c/198/

本博客所发布的内容,部分为原创文章,转载注明来源,网络转载文章如有侵权请联系站长!

(0)
上一篇 6天前
下一篇 6天前

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注