声明式(declaration)告诉编译器某个东西的名称和类型,但略去细节。
extern int x;
class Widget;
每个函数的声明式揭示其签名式(signature),也就是参数和返回类型。
std::size_t function(int);
定义式(definition)的任务是提供编译器一些声明式所遗漏的细节。对对象而言,定义式是编译器为此对象拨发内存的起点。对function或是function template而言,定义提供了代码本体。对class class template而言,定义列出了他们的成员。
C++提供了关键字explicit,可以阻止不应该允许的经过转换构造函数进行的隐式转换的发生。声明为explicit的构造函数不能在隐式转换中使用。
explicit构造函数是用来防止隐式转换的。
被声明为explicit的构造函数通常比其non-explicit更受欢迎,因为它们禁止编译器执行非预期(往往也不被期望)的类型转换。除非有一个好理由允许构造函数被用于隐式类型转换,否者直接使用explicit进行声明。
copy构造函数被用来"以同型对象初始化自我对象"
copy assignment操作符被用来"从另一个同型对象中拷贝其值到自我对象"
copy构造与copy赋值的区别:如果一个新对象被定义,一定会有个构造函数被调用,不可能调用赋值操作;如果没有新对象被定义,就不会有构造函数被调用,那么就是赋值操作被调用。
函数的pass-by-value意味着"调用copy构造函数",以by-value传递用户自定义类型通常是坏主意,pass-by-reference-const往往是较好的选择。
class Widget
{
public:
Widget(); //默认构造
Widget(const Widget& rhs); //拷贝构造
Widget& operator=(const Widget& rhs); //拷贝赋值
...
}
Widget w1; //默认构造
Widget w2(w1); //拷贝构造
Widget w3 = w2; //拷贝构造
Widget w4;
w4 = w3; //拷贝赋值
function1(w4); //拷贝构造
w4 = function2(); //拷贝赋值
STL标准模板库(Standard Template Library):容器(vector,list,set,map)、迭代器(vector<int>::iterator,set<string>::iterator)、算法(for_each,find,sort)等
#include <iostream>
class A; //类的声明式
class B; //类的声明式
class A
{
public:
A(); //默认构造,函数的声明式
A(int n);
A(const A& rhs); //拷贝构造,函数的声明式
A& operator=(const A& rhs); //拷贝赋值,函数的声明式
~A();
int print(); //返回num值,函数的声明式
private:
int num; //对象的定义式
};
A::~A()
{
num = 0;
std::cout << "delete" << num << std::endl;
}
A::A() :
num(0)
{
std::cout << "default! num = " << num << std::endl;
}
A::A(int n) //函数的定义式
{
num = n;
std::cout << "A num = " << num << std::endl;
}
A::A(const A& rhs) //函数的定义式
{
num = rhs.num;
std::cout << "copy = " << num << std::endl;
}
A& A::operator=(const A& rhs) //函数的定义式
{
num = rhs.num;
std::cout << "copy assignment = " << num << std::endl;
}
int A::print() //函数的定义式
{
return num;
}
class B //类的定义式
{
public:
explicit B(int n)
{
num = n;
std::cout << "B num = " << num << std::endl;
}
private:
int num;
};
void function1(A a)
{
std::cout << "function1 a-" << a.print() << std::endl;
}
A function2()
{
A a(10);
return a;
}
int main()
{
A a(12); //显示调用其默认拷贝构造函数,成功
function1(a); //拷贝构造
A b = 22; //隐式调用其默认拷贝构造函数,成功
A d(a); //拷贝构造
b = d; //拷贝赋值
A e = a; //拷贝构造
A f; //默认构造函数
A g = function2(); //调用了带参数的构造函数
f = function2(); //赋值构造
std::cout << "a-" << a.print() << std::endl
<< "b-" << b.print() << std::endl
<< "d-" << d.print() << std::endl
<< "e-" << e.print() << std::endl
<< "f-" << f.print() << std::endl
<< "g-" << g.print() << std::endl;
std::cout << "hello world!" << std::endl;
B c(11); //显示调用其默认拷贝构造函数,成功
//B d = 21;//编译错误,不能隐式调用其构造函数
//B d{21}; //编译错误,不能隐式调用其构造函数
return 0;
}