分享

构造函数

 印度阿三17 2018-09-26

这节不讲述构造函数的一般用法和概念。

1. 构造函数的类型转换功能

单参数构造函数的类型转换功能是指,如果类定义中提供了只带一个参数(没有其他参数或其他参数都有默认值)的构造函数,则当一个其他类型的数值或变量x赋值(注意不是初始化)给该类的对象A时,由于类型不一致,系统自动以x为实参调用该类的单参数构造函数,创建一个该类的临时对象,并将临时对象赋给A,实现隐式类型转换。

如下:

//类Money的定义
class Money{
    int yuan;
    int jiao;
    int fen;
public:
    Money(double d);
    Money(int yuan, int jiao, int fen);
    Money() { cout << "调用默认的构造函数" << endl; };
};

构造函数如下:

Money::Money(double d)//隐式类型传换的构造函数
{
    yuan = (int)d;
    jiao = (int)(d * 10) % 10;
    fen = (int)(d * 100) % 10;
    cout << yuan << "元" << jiao << "角" << fen << "分" << endl;
}

Money::Money(int yuan, int jiao, int fen)
{
    this->yuan = yuan;
    this->jiao = jiao;
    this->fen = fen;
    cout << this->yuan << "元" << this->jiao << "角" << this->fen << "分" << endl;
}

主函数调用方法:

int main()
{
    Money m1=3.14;//这是初始化对象,所以编译器将其转换为Money m1(3.14),所以不是类型转换
    Money m2(1, 3, 5);
    Money m3;//会首先调用空的构造函数
    m3 = 4.12;//此时调用类型转换功能的构造函数
    return 0;
}

所以调试结果如下:
在这里插入图片描述

总结:当采用先定义对象,然后对对象进行赋值时,采用类型转换功能的构造函数会被调用,也就是说此时对象会调用两次不同的构造函数。

2. 拷贝构造函数

拷贝构造函数的形参是本类的对象的引用。其作用是使用一个已经存在的对象去初始化一个新的同类的对象

形式:

ClassName::ClassName(ClassName &c)
{
    ......//函数体完成对应数据成员的赋值
}
实例如下:

//类的定义
class Money{
    int yuan;
    int jiao;
    int fen;
public:
    Money(double d);
    Money(int yuan, int jiao, int fen);
    Money() { cout << "调用默认的构造函数" << endl; };
    Money(Money &c);
    void print();
    int Getyuan();
    int Getjiao();
    int Getfen();
};

拷贝构造函数的定义:

Money::Money(Money & c)
{
    yuan = c.yuan;
    jiao = c.jiao;
    fen = c.fen;
    cout << "调用拷贝构造函数" << endl;
}

两个函数:

Money Max(Money& a, Money& b)
{
    if (a.Getyuan() > b.Getyuan())
        return a;
    else if(a.Getyuan()<b.Getyuan())
        return b;
    else
    {
        if (a.Getjiao() > b.Getjiao())
            return a;
        else if (a.Getjiao() < b.Getjiao())
            return b;
        else
        {
            if (a.Getfen() > b.Getfen())
                return a;
            else if (a.Getfen() < b.Getfen())
                return b;
            else
                cerr << "两个数值相同" << endl;
            return 0;
        }
    }
}
Money Min(Money a, Money b)
{
    if (a.Getyuan() < b.Getyuan())
        return a;
    else if (a.Getyuan()>b.Getyuan())
        return b;
    else
    {
        if (a.Getjiao() < b.Getjiao())
            return a;
        else if (a.Getjiao() > b.Getjiao())
            return b;
        else
        {
            if (a.Getfen() < b.Getfen())
                return a;
            else if (a.Getfen() > b.Getfen())
                return b;
            else
                cerr << "两个数值相同" << endl;
            return 0;
        }
    }
}

函数中可以看出区别在于形参中一个使用的是类的别名,一个使用的是类的对象

主函数调用:

int main()
{
    Money m1=1.35;
    Money m2(1, 3, 6);
    //Money m3;
    //m3 = 4.12;
    //Money m4 = m3;
    //m4.print();
    Money max;
    max=Max(m1, m2);
    cout<<"钱最大为:"<<endl;
    max.print();
    Money min;
    min = Min(m1, m2);
    cout << "钱最小为:" << endl;
    min.print();
    return 0;
}

调试结果如下:

拷贝构造函数调用情况:

当用类的一个对象去初始化另一个对象时;
当调用一个含有类的对象参数的函数时;
函数的返回值是类的对象时;
系统会自动生成一个默认的拷贝构造函数,功能是把初始值对象的每个数据成员的值都赋给新建立的对象。

注意:对于类中包含指向动态内存的指针的情况,若使用默认的拷贝构造函数复制对象会带来严重的问题。析构的时候会将同一片堆析构两次
在这里插入图片描述

3. 对象成员和构造函数

一个类的对象可以作为另一个类的数据成员,此时把该对象成为类的对象成员。

注意:

当一个类中出现对象成员时,该类的构造函数就要为对象成员初始化,必须在构造函数的初始化列表中完成。
若未在该类的构造函数初始化列表中给出对象成员的初始化项,则调用对象成员的默认构造函数
若包含多个对象成员,对象成员的构造函数的调用顺序由他们在该类中的说明顺序有关,而与初始化表中的顺序无关
初始化对象成员时必须用对象成员名,而不是类型名。
若一个类中含有多个对象成员,则可在该类的初始化列表中列出多个对象成员的初始化项,以逗号隔开。
若一个类包含对象成员,建立该类对象时,先调用对象成员的构造函数,初始化相应的对象成员,才执行构造函数,初始化该类的其他数据成员。
实例如下:

void my_strcmp(char *a, char const  *b);
class Money{
    int yuan;
    int jiao;
    int fen;
public:
    Money(double d);
    Money(int yuan, int jiao, int fen);
    Money() { cout << "调用默认的构造函数" << endl; };
    Money(Money &c);
    void print();
    int Getyuan();
    int Getjiao();
    int Getfen();
};
class Person {
    Money money;
    char name[10];
    int age;
public:
    Person(char const *name, int age) :money(3.14) 
    { 
        my_strcmp(this->name,name); 
        this->age = age;
    };
    void print();
};

代码中类Person中包含了类Money。调用如下:

int main()
{
    Person p1("liming",14);
    p1.print();    
    return 0;
}
void Person::print()
{
    cout << name << endl;
}

调试结果如下:

在这里插入图片描述

可以看出其首先调用的是Money的构造函数,然后调用Person类的,同时先初始化对象成员
在这里插入图片描述

将程序中的Person构造函数改为

Person(char const *name, int age)
    { 
        my_strcmp(this->name,name); 
        this->age = age;
        cout << "调用Person的构造函数" << endl;
    };

也就是不初始化对象成员,则先调用对象成员的默认构造函数,然后调用Person的构造函数。

来源:http://www./content-4-25161.html

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多