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;
}
也可以加后缀_
使用构造函数
- 显式调用构造函数
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;默认构造函数不会进行任何操作
Stock::Stock();
只创建对象,并不进行初始化,默认构造函数也没有参数。编译器只有在没有定义任何构造函数时,才会提供默认构造函数。为类定义了构造函数后,我们就必须提供默认构造函数,如果只提供了非默认构造函数而没有提供默认构造函数
Stock s1;//这种调用默认构造函数将会出错
如果要创建对象且不显式地初始化,则必须定义一个不接受任何参数的默认构造函数,定义默认构造函数的方式有两种
- 给定构造函数所有参数提供默认值
Stcok(const string &co = “error”,int n = 0,double pr = 0.0); - 通过函数重载定义另一个构造函数
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;
}
输出结果:
说明一下代码
首先用两种方式分别创建了s1和s2俩个对象,第一种通过构造函数初始化对象,第二种,先调用构造函数创建一个临时对象并初始化然后赋值给s2,将一个对象赋给同类型的另一个对象时,C++将源对象的每个数据成员的内容复制到目标对象对应的数据成员中。
构造函数不仅仅可以初始化新对象,还可以给已存在的对象重新赋值,和上面第二种是一样的。main函数调用完之后,会调用析构函数,因为是存储在栈中的对象,所以先进后出,先清理后创建的对象。
我们尽量使用不产生临时对象的方式来初始化对象,会增加程序的效率
网站标题:CV鼻祖洋芋
原创文章,作者:locus,如若转载,请注明出处:https://blog.cvpotato.cn/forward-code/c/198/
本博客所发布的内容,部分为原创文章,转载注明来源,网络转载文章如有侵权请联系站长!