C++类的构造函数详解
1.默认构造函数
1) 当没有定义任何构造函数时,编译器会提供默认构造函数,可以直接使用。
2) 如果定义了带参数的构造函数,又需要使用默认构造函数,此时,必须显式定义无参构造函数,这和C#中有很大的不同。例如有一个蔬菜类Veg:
Veg(const char* name,int num,double price);//声明了带三个参数的构造函数
要初始化Veg对象,可使用
Veg veg("tomato",15,3.5);
3) 定义了带参数的构造函数的同时,又需要使用Veg veg;若带参数的构造函数,参数全部用默认值,如:
Veg(const char* name="NONE",int num=0,double price=0.0);
则可成功初始化对象,否则将报错,
若要使用默认构造函数,必须显式声明
Veg veg();//声明了默认构造函数
2.创建并初始化对象的几种方式
1)Veg veg("tomato",15,3.5);
在栈中,创建一个名为veg的Veg对象,并调用构造函数初始化
2)Veg veg=Veg("tomato",15,3.5);
和方法一原理一样
3)Veg veg;
无参构造函数或参数全部有默认值的构造函数的初始化
以上三种方式创建的对象,是放在栈中的,当作用域结束时,析构函数将被隐式调用,对象将被释放。
4)Veg *p = new veg("tomato",15,3.5);
在堆中,创建一个Veg对象,并调用构造函数初始化,并返回指向该对象的指针p
关于new的详细介绍,可参考 C++ new操作符详解
堆中创建的对象,在不需要使用时,要使用delete关键字,删除指针,此时析构函数会立即被隐式调用,指针指向的对象将被释放,
否则的话,将造成内存泄漏。
3.对象赋值
Veg veg1=Veg("tomato",15,3.5);
Veg veg2 = veg2;
属于值传递,对象中每个数据成员的值都将复制到目标对象相应的数据成员。
4.关于只带一个参数的构造函数
只有一个惨的构造函数初始化时,可以将对象初始化为该参数,语法如下:
Classname object= value;
编程时,我们使用了很多此种初始化方式,简洁明了,如:
int a(10)=>int a = 10;
string a("hello")=>string a= "hello";
然而,很多时候,此种初始化方式,是不对的。如:
针对构造函数Veg(const char* name);我们可以直接初始化为:
Veg veg = name;
显然,Veg对象并不是一个char*类型的字符串,那么如何避免误用此种初始化方式呢?
可在构造函数声明时,加上explicit关键字,如:explicit Veg(const char* name);
explicit关键字的详细介绍,可参考 C++ explicit关键字
5.构造函数使用示例
如下例所示,定义了一个蔬菜类Veg,main函数中演示了几种构造函数初始化方式。
Veg.h
#pragma once #include<iostream> #include<string> class Veg { private: std::string name; int num; double price; double total; void set_tot(){total = num*price;} public: Veg(); Veg(const std::string &name); Veg(const std::string &name,int num=0,double price = 0.0); ~Veg(); void show(); };
Veg.cpp
#include "Veg.h" Veg::Veg() { name="NONE"; num = 0; price = 0.0; total = 0.0; } Veg::Veg(const std::string &name) { this->name=name; } Veg::Veg(const std::string &name,int num,double price) { this->name = name; this->num = num; this->price = price; set_tot(); } Veg::~Veg() { std::cout<<"~Veg()"<<std::endl; } void Veg::show() { std::cout<<"name:"<<name<<" num:"<<num<<" price:"<<price<<" total:"<<total<<std::endl; }
useveg.cpp
#include "Veg.h" int main() { Veg veg1; Veg veg2("tomato",15,3.5); Veg veg3=Veg("potato",8,2.0); Veg *p=new Veg("tomato",15,3.5); veg1.show(); veg2.show(); veg3.show(); veg2 = veg3; veg2.show(); veg3.show(); delete p; p=NULL; return 0; }
运行结果:
参考资料:《C++ Primer.Plus》 pp.352-363