Classes control object initialization by defining one or more special member functions known as constructors.

  • 跟func很像,但是不能const;且由于名字和class一样,所以遵循overloaded的规则;而且它只做一件事,没有返回值
  • A constructor is run whenever an object of a class type is created.
  • constructors have a (possibly empty) parameter list and a (possibly empty) function body.
struct Sales_data {
	// constructors added 
	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 &); 
	// other members as before 
	std::string isbn() const { return bookNo; } 
	Sales_data& combine(const Sales_data&); 
	double avg_price() const; 
	std::string bookNo; 
	unsigned units_sold = 0; 
	double revenue = 0.0;
};
 
Sales_data::Sales_data(std::istream &is) {
	read(is, *this);  // read will read a transaction from is into this object 
}

Default Constructor

其实就是当没给 initializers 的时候,所 initial 的,就是 default 的 (⚠️ 注意,没给 initializers 所对应的 default 方案有多种:)

  • 当class中没有明确定义任何constructors,那就会隐含一个默认的构造函数。也就是说,如果有其他的构造函数,就不会隐含一个默认的,就好比上面例子的第一句话

  • 使用 =defalut

  • A constructor that supplies default arguments for all its parameters also defines the default constructor.
    (这里的DA应该说的就是我没给任何arguments但是依旧有东西进去了。对应有1. funcs中的默认参数 2. delegating constructor。巧妙利用这一条可以将default和别的合二为一)

我想也是因为有最后一条规则,才会出现第一条的高光部分吧。

Constructor Initializer List

在理解这个东西之前,先好好想想 initialassign 的区别。没错,区别就在这,这也是为什么constructor initializer list的书写规范是这样的

写在block中的,是作为 assign 的,而 initial 是发生在这个obj be created的时候(aka初始化发生在赋值之前,进入block的时候,initial就已经完成了)。这也是为什么书写规范是这样的:在block之前,在initializers之后。

第一句话就说了,是一个特殊的函数。确实,这个东西在block内做的事情不是init. 【猜想】有这个block只是为了让所谓的“initial”更加的灵活,做更多的事

Order of Member Initialization

constructor中的para顺序并不影响初始化的顺序,影响的是这些member在class中的定义的先后。

最好是按照mem的声明顺序来给para的顺序,并且最好不要用mem来init mem(因为有可能会让一个mem用上另一个undefined mem)

Delegating Constructors

class Sales_data { 
public:
	// nondelegating constructor initializes members from corresponding arguments 
	Sales_data(std::string s, unsigned cnt, double price):
		bookNo(s), units_sold(cnt), revenue(cnt * price) { } 
	// remaining constructors all delegate to another constructor 
	Sales_data(): Sales_data("", 0, 0) {} 
	Sales_data(std::string s): Sales_data(s, 0,0) {} 
	Sales_data(std::istream &is): Sales_data() { read(is, * this); } 
	// other members as before
};

允许一个constructor在自己的class中找另一个constructor来帮忙init(我想目的应该还是那纯真的简洁)

在原本 initializer list 处直接调用别的 constructor,可以直接给定 arguments(delegate可以嵌套)

控制流:delegting接收参数,调用delegated-to的全部包括function body,回到delegating的body

Class-Type Conversion

单参 constructor 定义了一个 implicit type conversion 就是当需要隐式类型转换的时候,单参构造函数会被调用

string null_book = "9-999-99999-9";
// constructs a temporary Sales_data object 
// with units_sold and revenue equal to 0 and bookNo equal to null_book 
item.combine(null_book);
/* ==^== */
// assignment create a type conversion context
Sales_data book = null_book;

⚠️ Only One Class-Type Conversion Is Allowed

有时这样的 conversion 也不是我们想要的,因为这样出来的 obj 都是 temporary,想再用就无了,所以我们可以给构造函数加上 explicit

因为是 explicit 不把 static_cast< > 叫出来玩玩多不礼貌:

item.combine(static_cast<Sales_data>(cin));