(一)
如下写
class Empty { };
好比如如下下(这些函数被调用,它们才被编译器创建出来。
class Empty {
public:
Empty() {...}
Empty(const Empty& rhs) {...}
~Empty() {...} //编译器产出的析构函数是个non-virtual,除非这个class的base class自身声明有virtual析构函数。
Empty& operator=(const Empty& rhs) {...}
};
void main()
{
Empty e1; //构造函数
Empty e2(e1);//拷贝构造函数
e2=e1;//操作符
//析构函数
//析构函数
}
(二)
如下:
#include <iostream>
using namespace std;
template<typename T>
class NamedObject {
public:
NamedObject(const char* name, const T& value){nameValue=name; objectValue=value;};
NamedObject(const string& name, const T& value){cout << "2" <<endl;};
private:
string nameValue;
T objectValue;
};
void main()
{
NamedObject<int> no1("Smallest Prime Number", 2);
NamedObject<int> no2(no1);//调用默认的copy构造函数
}
copy构造函数的调用过程:编译器生成copy构造函数,会以no1.nameValue和no1.objectValue为初值来设定no2.nameValue和no2.objectValue.
由于nameValue是string类型。所以no2.nameValue的初始化方式是调用string的copy构造函数并以no1.nameValue为实参。另一个是内置类型。no2.objectValue会以“拷贝no1.objectValue内的每一个bits"来完成初始化。
(三)赋值操作符的基本行为与上面的拷贝构造函数如出一辙,但有里那个类外:
第一个例外:
#include <iostream>
using namespace std;
template<typename T>
class NamedObject {
public:
NamedObject( string& name, const T& value):nameValue(name), objectValue(value){};
private:
string& nameValue; //reference
const T objectValue; //const
};
void main()
{
string newDog("persephone");
string oldDog("Satch");
NamedObject<int> p(newDog,2);
NamedObject<int> s(oldDog,36);
//p=s;
}
拒绝赋值操作 因为reference不能指向不同的对象!
解决:如果打算在”内含reference成员“的class内支持赋值操作。必须自己定义赋值操作符。面对内含const成员,编译器也一样,更改const成员是不合法的,所以编译器也不知道如何在自己的 赋值函数内面对他们。
自己定义赋值操作符:
#include <iostream>
using namespace std;
template<typename T>
class NamedObject {
public:
NamedObject( string& name):nameValue(name){};
void operator=(const NamedObject& rhs)
{
nameValue=rhs.nameValue;
}
private:
string& nameValue; //reference
};
void main()
{
string newDog("persephone");
string oldDog("Satch");
NamedObject<int> p(newDog);
NamedObject<int> s(oldDog);
p=s;
}
另一个例外是 基类将赋值操作符声明为private了。编译器将拒绝为子类生成一个赋值操作符。
请记住:
编译器可以暗自为类创造 默认构造函数,拷贝构造函数,赋值操作符,和析构函数。