Fork me on GitHub

C++:类、类的构造与析构

概念引述

  C++的OOP特点已经耳熟能详,封装,继承,多态。封装主要体现在namespace、stock、funtion;继承体现为类继承;多态体现为类之间通过继承关联时。因此C++进阶的前提就是熟知类的使用,明白类是创建数据和操作数据的一种重要方法。

类的访问权限

引自https://www.runoob.com/cplusplus/cpp-inheritance.html

类的定义与实现

//头文件
class Stock
{
private:
	std::string cpy_name;//股票名
	long shares;//股票的股数
	double val_share;//单只股票的价格
	double tol_value;//股票的总价值
	void set_total()//只在类的内部可见,声明+定义
	{
		Stock::tol_value = Stock::shares * Stock::val_share;
	}
public:
	Stock(const std::string& co, long n, double price);//构造函数
	~Stock();//析构函数
	void buy(long n, double price);
	void sell(long n, double price);
	void update(double price);
	void show();
};
#include <iostream>
#include "stock00.h"

//构造函数
Stock::Stock(const std::string& co, long n, double price)
{
	Stock::cpy_name = co;
	if (n < 0)
	{
		std::cout << "number of shares is negative!" << std::endl;
		Stock::shares = 0;
	}
	else
	{
		Stock::shares = n;//股票的股数
		Stock::val_share = price;//每股的价格
		Stock::set_total();//总价格
	}
}

//析构函数
Stock::~Stock()
{
	std::cout << "调用析构函数:" << cpy_name << std::endl;
}

void Stock::buy(long n, double price)
{
	if (n < 0)
	{
		std::cout << "number of shares is negative! transaction is fail!" << std::endl;
		Stock::shares = 0;
	}
	else
	{
		Stock::shares += n;
		Stock::val_share = price;//每股的价格
		Stock::set_total();//总价格
	}
}

void Stock::sell(long n, double price)
{
	if (n < 0)
	{
		std::cout << "number of shares is negative! transaction is fail!" << std::endl;
		Stock::shares = 0;
	}
	else if (n > shares)
	{
		std::cout << "number of shares is over! transaction is fail!" << std::endl;
	}
	else
	{
		Stock::shares -= n;
		Stock::val_share = price;//每股的价格
		Stock::set_total();//总价格
	}

}
void Stock::update(double price)
{
	Stock::val_share = price;//每股的价格
	Stock::set_total();//总价格
}

void Stock::show()
{
	std::cout << "Company: " << Stock::cpy_name << std::endl;
}

  类中一般包含私有和共有两部分,私有对象不允许外部访问,只能通过共有的函数去间接访问。除此之外对于那些出于隐藏的目的不宜设为公有,但又确实需要在派生类的成员函数中经常访问的基类成员,将它们设置为protected保护成员,既能起到隐藏的目的,又避免了派生类成员函数要访问它们时只能间接访问所带来的麻烦。需要说明的是:

  • 当声明时进行类成员函数定义,类成员函数将成为内联函数
  • 类定义于栈中,因此是先入后出的关系,这一点在调用析构函数时可以显示观察到
  • 类对象可以互相拷贝
  • 类的保护对象可以如同共有部分一样在派生类与基类中进行访问

类的构造

  类的构造我们一般称之类的构造函数,类的构造函数通常用来定义类并给类对象赋值。从“类定义的定义与实现”代码可以看到,类的构造函数形式为:

Stock(const std::string& co, long n, double price);//构造函数,类的构造函数必须与类名一致

  创建类时:

Stock ob_cat= Stock("zw",10,12);//构造函数的显示调用
Stock ob_cat("zw",10,12);//构造函数的隐式调用

  另外,C++提供了默认构造函数,如果我们没有定义构造函数,在创建类时C++编译器会自行创建一个类的默认构造函数。类的默认构造函数创建有以下三种方式

//第一种:不创建构造,C++自行创建一个默认构造函数
//stock::stock() {}

//第二种:传递默认参数创建默认构造函数
Stock(const std::string& co = "zw" , long n = 1, double price = 10);

//第三种:默认构造函数的函数重载
Stock();

  仍然需要注意,传递默认参数时,默认参数必须处于形参列表的最后。在C++11中,也提供了构造函数的新用法{}:

stock ob_cat = { "fff", 1.2, 5.5 };//C++11的新用法

类的析构

  类的析构类似于new然后delete,自动执行类的清理工作,所以一般只是定义出来或者干脆不定义,而在析构函数中不做任何操作,如果没有定义析构函数,C++编译器将执行与默认构造函数相同的操作---自行定义一个默认的析构函数。

Stock::~Stock()
{
	std::cout << "调用析构函数:" << cpy_name << std::endl;
}

  所以析构函数的执行通常在程序生命周期的末节,比如当我们新建一个int main(void)函数运行上述定义的代码时,可以显式观察到构造函数的执行顺序,这里大家只需关注构造函数的执行步骤即可:

  这里能观察到当我们在第一步重新调用一个构造函数进行类对象的赋值时,析构函数被调用。这是因为当调用构造函数进行类对象的二次复制时,本质是新建了一个临时类对象,并将其值赋值给原先的类对象,随后将仙剑的临时类对象删除,此时会调用析构函数。除此之外,如果我们再构造函数进行new,对应的在析构函数也需要delete!

Const与类对象

  现在我们知道,类本质就是数据的创建与操作,那如果我们想创建一个不被修改的类对象时,只是打印其中内容应该怎末办呢?C++仍然规定了类成员的cosnt限定规则,拿上面定义的show()函数来说:

void show() const;

  如果不这样做,编译器无法保证const 类对象进行打印时不被修改!

posted @ 2022-10-11 22:26  张一默  阅读(138)  评论(0编辑  收藏  举报