C++ 之类的函数

类的基本思想是数据抽象封装,数据抽象是一种依赖于接口实现分离的编程艺术。封装实现了类的接口和实现的分离。封装后的类隐藏了它的实现细节。

成员函数

成员函数的声明必须放在类的内部,它的定义既可以在类的内部也可以放在外部。作为接口组成部分的非成员函数,它们的定义和声明都在类的外部。

class Sales_data {
friend Sales_data add(const Sales_data&, const Sales_data&);
friend std::ostream &print(std::ostream&, const Sales_data&);
friend std::istream &read(std::istream&, Sales_data&);
public:
    Sales_data() = default;//默认构造函数
    Sales_data(const std::string &s): bookNo(s) { }
    Sales_data(const std::string &s, unsigned n, double p):
               bookNo(s), units_sold(n), revenue(p*n) { }
    Sales_data(std::istream &);

    // operations on Sales_data objects
    std::string isbn() const { return bookNo; }
    Sales_data& combine(const Sales_data&);
    double avg_price() const;
private:
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};


// 非成员函数放在类的外面
Sales_data add(const Sales_data&, const Sales_data&);
std::ostream &print(std::ostream&, const Sales_data&);
std::istream &read(std::istream&, Sales_data&);

成员函数之this

当我们调用total.isbn()的时候,成员函数通过一个名为this的额外的隐式参数来访问调用它的那个对象。当我们调用一个成员函数时,用请求该函数的对象地址初始化this。也就是说:

    std::string isbn() const { return bookNo; }

等价于

std::string isbn() const { return this->bookNo; }

因为this总是指向“这个”对象,所以this是一个常量指针。

const成员函数

isbn函数的另一个关键之处是紧随参数列表之后的const关键字,const的作用是修改隐式this指针的类型。

this是隐式的并且不会出现在参数列表中,所以在哪里将this声明成指向常量的指针就成为我们必须面对的问题。c++做饭是允许把const关键字放在成员函数的列表之后,此时,紧跟在参数列表后面的const表示this是一个指向常量的指针。像这样使用const的成员函数被称作常量成员函数。

可以把isbn的函数体想象成如下的形式:

    //此代码是非法的只是为了说明隐式this是如何使用的
    //非法的原因是我们不能显示的定义自己的this指针
    //此处的this是一个指向常量的指针,因为isbn是一个常量成员
    //因为this是指向常量的指针,所以常量成员函数不能改变调用它的对象的内容。
    //isbn可以读取调用它的对象的数据成员,但是不能写入新值。
    std::string Sales_data::isbn(const Sales_data *const this)  { return this->isbn; }

定义一个返回this对象的函数

Sales_data& 
Sales_data::combine(const Sales_data &rhs)
{
    units_sold += rhs.units_sold; // 把rhs的成员加到this对象的成员上
    revenue += rhs.revenue;       
    return *this; // 返回调用该函数的对象
}

该函数值得注意的是他的返回类型和返回语句。内置的赋值运算符把他的左侧运算对象当成左值返回,因此为了与它保持一致,conbine函数必须返回引用类型。

调用一个返回引用的函数得到左值,其他返回类型得到右值。

构造函数

构造函数的名字和类名相同。和其他函数不同的是,构造函数没有返回类型,构造函数不能被声明为const的。

如果我们的类并没有显示定义构造函数,编译器就会为我们隐式的定义一个默认构造函数。

编译器创造的构造函数又被称为合成的默认构造函数。
合成的默认构造函数按照如下规则初始化类的数据成员:
1. 如果存在类内初始值,用它来初始化成员
2. 否则,默认初始化该成员。

某些类不能依赖于合成的默认构造函数

原因:
1. 编译器只有在发现类不包含任何构造函数的情况下,才会替我们生成一个默认的构造函数。一旦我们定义了构造函数,除非我们自己定义默认构造函数,否则类将没有默认构造函数。
2. 对于某些类来说,合成的默认构造函数可能执行错误的操作。因为定义在块中的内置类型或复合类型的对象(数组或指针)被默认初始化,则它们的值将是未定义的。这样用户在创建类的对象的时候可能会得到未定义的值。
3. 有的时候编译器不能为某些类合成默认的构造函数。例如如果类中包含一个其他类类型的成员,且这个成员的类型没有默认构造函数,那么编译器将无法初始化该成员。

猜你喜欢

转载自blog.csdn.net/u011337574/article/details/79155946