前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >构造函数和析构函数

构造函数和析构函数

作者头像
用户7272142
发布2023-10-11 21:18:29
1640
发布2023-10-11 21:18:29
举报
文章被收录于专栏:Republic博客Republic博客

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

声明和定义构造函数

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

代码语言:javascript
复制
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_前缀

代码语言:javascript
复制
class Stock
{
private:
string m_commpany;
long m_shares;
}

也可以加后缀_

使用构造函数

显式调用构造函数 Stock food = Stock("World Cabbage",250,1.25); 这样就初始化food对象的成员

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

默认构造函数

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

代码语言:javascript
复制
Stock::Stock();

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

代码语言:javascript
复制
Stock s1;//这种调用默认构造函数将会出错

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

给定构造函数所有参数提供默认值 Stcok(const string &co = "error",int n = 0,double pr = 0.0);

通过函数重载定义另一个构造函数 Stock(); 实际上,默认构造函数应为所有成员提供初始值

代码语言:javascript
复制
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,那么析构函数也不需要其他操作

代码语言:javascript
复制
Stock::~Stock();

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

代码语言:javascript
复制
//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

代码语言:javascript
复制
//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';
}

代码语言:javascript
复制
//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
image.png

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

本文参与?腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-09-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 声明和定义构造函数
  • 使用构造函数
  • 默认构造函数
  • 析构函数
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com