【c++ primer, 5e】构造函数 & 拷贝、赋值和析构

【构造函数】

1、构造器就是创建对象时被调用的代码。

2、如果没有自定义构造器,那么编译器将自动合成一个默认的无参构造器。

3、自定义的构造器不允许加const,所创建const的对象只有在构造器代码执行完后,才被赋予const性质。

4、如果自定义了构造器,那么默认的构造器将无效化,可以理解为自定义内容覆盖了默认的内容。—— “要么什么都不做,要么全部都交给你来做。”

5、构造函数使用类内初始值并不是一个坏选择。

6、default。(在练习中体现)

7、构造函数初始值列表。(在练习中体现)

练习

7.11

ps:定义在类内的函数默认为内联的!类外的不是。(内联函数可以提高性能,那么,为什么不把所有函数都定义成内联函数呢?内联函数的优缺点

#include <iostream>
#include <string>
using namespace std;

// Sales_data.h
struct Sales_data {
    // 新增的构造函数
    Sales_data() = default; //全等同于合成默认构造器,不写就没有!!!
    Sales_data(const string &s): bookNo(s) {} // “:”到“}”之间为构造函数初始值列表
    Sales_data(const string &s, unsigned n, double p): bookNo(s), units_sold(n), revenue(p*n) {}
    Sales_data(istream&);
    // public部分,对象看起来是怎么样的。
    std::string isbn() const { return bookNo; } // inline function
    Sales_data& combine(const Sales_data&);
    double avg_price() const;
    // private部分,数据成员。
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};
// Sales_data的非成员接口函数
Sales_data add(const Sales_data&, const Sales_data&);
std::ostream &print(std::ostream&, const Sales_data&);
std::istream &read(std::istream&, Sales_data&);


// Sales_data.cpp
Sales_data& Sales_data::combine(const Sales_data &rhs)
{
    units_sold += rhs.units_sold;
    revenue += rhs.revenue;
    return *this;
}
istream &read(istream &is, Sales_data &item)
{
    double price = 0;
    is >> item.bookNo >> item.units_sold >> price;
    item.revenue = price * item.units_sold;
    return is;
}
ostream &print(ostream &os, const Sales_data &item)
{
    os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
    return os;
}
double Sales_data::avg_price() const {
    if (units_sold)
        return revenue/units_sold;
    else
        return 0;
}
Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
{
    Sales_data sum = lhs;
    sum.combine(rhs);
    return sum;
}
Sales_data::Sales_data(istream &is)
{
    read(is, *this);
}


// main.cpp
int main()
{
    Sales_data data1; // default
    Sales_data data2("ISOD233");
    Sales_data data3("ISOD233", 3, 22.5);
    Sales_data data4(cin);
    
    print(cout, data1) << endl;
    print(cout, data2) << endl;
    print(cout, data3) << endl;
    print(cout, data4) << endl;
    /* output:
     0 0 0
    ISOD233 0 0 0
    ISOD233 3 67.5 22.5
    DASD23 4 88 22
    */
        return 0;
}

7.12

就知道这题有坑。

prog1.cpp: In constructor 'Sales_data::Sales_data(std::istream&)':
prog1.cpp:13:17: error: 'read' was not declared in this scope
   read(is, *this);

翻了一下收藏的博客,发现这道题要用友元函数(下一小节)。

7.13

参考(不会写)。

Sales_data total(cin);
    if (total.units_sold > 0) {
        Sales_data trans;
        while (read(cin, trans)) {
            if (total.isbn() == trans.isbn())
                total.combine(trans);
            else {
                print(cout, total) << endl;
                total = trans;
            }
        }
        print(cout, total) << endl;
    } else {
        cerr << "No data?!" << endl; 
    }

7.14

是这样吗?

    Sales_data()
    {
        units_sold = 0;
        revenue = 0.0;
    }

7.15

测试无误。

    // constructor
    Person() = default;
    Person(const string &name): name(name) {}
    Person(const string &name, const string &address): name(name), address(address) {}
    Person(istream&);
Person::Person(istream &is)
{
    read(is, *this);
}

【拷贝、赋值和析构】

如果我们不主动定义这些操作,那么编译器将会替我们合成它们。

默认的析构函数将会在语句块结束时被调用,销毁局部变量。

某些类(管理动态内存的类)不能依赖于合成的版本,因此有时候不得不定义这些函数。

原文地址:https://www.cnblogs.com/xkxf/p/6673202.html