1.C++的空类中有哪些函数?
如果在C++的类中不声明任何成员,C++会自动为你生成默认的构造函数、默认的拷贝构造函数、析构函数、赋值运算符重载。所有的这些函数都是public且是inline的。如下例所示:
1class Empty{}; 2 3// 假定以下功能都会被调用,则等价于 4class Empty{ 5public: 6 Empty(){ // ...} // 默认构造函数 7 Empty(const Empty& rhs){ // ...} // 默认拷贝构造函数 8 ~Empty(){// ...} // 析构函数 9 10 Empty& operator=(const Empty& rhs){ // ...} // 赋值运算符重载 11};
当这些函数需要被调用时,编译器才会去创建它们。下面的代码将会使编译器将上述的每一个函数产生出来。
1Empty e1; // 调用默认构造函数和析构函数 2 3Empty e2(e1); // 调用默认拷贝构造函数 4e2 = e1; // 调用赋值运算符重载
注意:这样生成默认的函数是有条件的,因此无法保证上面的四种函数一定会都被自动生成。赋值运算符重载是为了将一个对象的成员数据拷贝进另一个对象中。对于赋值运算符重载,只有当代码合法而且有意义时,编译器才会自动生成。如下代码就不满足该条件:
1template<typename T> 2class A{ 3 public: 4 A(std::string& _name, const T& value); 5 private: 6 std::string& name; // 注意这个成员变量是string的引用哦! 7 const T value; // value只能读不能写! 8};
对于如上的类,现在执行如下操作:
1std::string s1("hello"); 2std::string s2("hi"); 3 4A<int> a1(s1,3); 5A<int> a2(s2,6); 6a1=a2;
C++中规定引用是专一的,一旦一个引用被绑定到一个对象后,它就不允许再指向另一个对象。如下例所示:
1int a=3; 2int& b=a; // b是a的引用 3int c=7; 4int& d=c; // d是c的引用 5b=d; //编译器在此当然会报错
因此,给类A的对象a1成员变量name再赋值会导致编译出错。同样,C++也不允许为常量再赋值,因此对成员value赋值也会编译出错。
解决方法:如果你打算在一个内部含有引用类型的成员变量的类中支持赋值操作,那么你必须自己定义赋值运算符重载函数;对于一个内部含有const成员变量的类中支持赋值操作,你也必须自己定义赋值运算符重载函数。
此外,当基类将赋值运算符重载函数声明为私有(private)时,编译器也会拒绝为它的子类生成默认的赋值运算符重载函数。因为在子类赋值过程中,它所包含的基类也应当被赋值。但是既然被声明为基类的私有成员,子类将不能调用。
2.总结
(1).编译器可以默认为类自动创建默认构造函数、拷贝构造函数、赋值运算符重载函数、析构函数。