• 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

  • 相关阅读:
    css如何去掉select原始样式
    Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL
    eclispe+maven+ssm+sql_server/mysql配置
    解决Missing artifact com.microsoft.sqlserver:sqljdbc4:jar:4.0问题
    eclipse alt+/智能提示错误问题
    去除input边框 input去除边框 去除input获取焦点时的蓝色外边框
    java对sql server的增删改查
    java连接sql server 2008
    卸载sql server 2008
    FTP的vsftpd.conf含义
  • 原文地址:https://www.cnblogs.com/shijingjing07/p/5546014.html
Copyright © 2020-2023  润新知