c++的一些默认函数
2014-04-05 19:40
323 查看
一个空的类在C++编译器处理过后就不再为空,编译器会自动地为我们声明一些member function,一般编译过去就相当于
class Empty
{
public:
Empty(); // 缺省构造函数
Empty( const Empty& ); // 拷贝构造函数
~Empty(); // 析构函数
Empty& operator=( const Empty& ); // 赋值运算符
Empty* operator&(); // 取址运算符
const Empty* operator&() const; // 取址运算符 const
};
一般的书上好像都是前面四种:默认构造函数,拷贝构造函数,默认赋值函数以及析构函数,后面两种其实属于,但要需要注意的是,只有当你需要用到这些函数的时候,编译器才会去定义它们。
如果你只是声明一个空类,不做任何事情的话,编译器会自动为你生成一个默认构造函数、一个拷贝默认构造函数、一个默认拷贝赋值操作符和一个默认析构函数。这些函数只有在第一次被调用时,才会别编译器创建。所有这些函数都是inline和public的。
如果你打算在一个“内含引用成员”或者“内含const成员”的类内支持赋值操作,就必须定义自己的默认拷贝赋值操作符。
当基类将自己的默认拷贝赋值操作符声明为private时,子类就不会产生自己的的默认拷贝赋值操作符。因为假如产生了这样的默认拷贝赋值操作符,它无权去调用基类的private部分,
你可以将拷贝构造函数或默认拷贝赋值操作符声明为private。这样明确声明一个成员函数,就阻止了编译器暗自创建的默认版本,而这些函数为private,使得可以成功阻止人们调用它。
上面的做法有一个隐患,因为类自身的member和friend还是可以调用这些private函数。有一个很刁钻的方法,“将成员函数声明为private而且故意不实现它们”,这样既阻止了默认函数的生成,而且如果你试着调用这些函数,就会得到一个链接错误。只声明,不定义,链接器报错。甚至在声明的时候,你连参数也不用写。
而试着将上述的链接器错误提前到编译器也是可以的。我们专门设计一个类Unconpyable。
--------------------------------------------------------------------
class Uncopybale {
protected:
Uncopyable() {}
~Uncopyable() {}
private:
Ucopyable(const Uncopyable&)
Uncopyable& operator=(const Uncopyable&)
};
--------------------------------------------------------------------
为了阻止对象被拷贝,我们唯一需要做的就是继承Uncopyable。这些函数的默认生成版本会尝试调用其基类的对应版本,那些调用会被编译器拒绝,因为它基类的拷贝函数是private。
Boost提供的noncopyable类也有类似的功能。
class Empty
{
public:
Empty(); // 缺省构造函数
Empty( const Empty& ); // 拷贝构造函数
~Empty(); // 析构函数
Empty& operator=( const Empty& ); // 赋值运算符
Empty* operator&(); // 取址运算符
const Empty* operator&() const; // 取址运算符 const
};
一般的书上好像都是前面四种:默认构造函数,拷贝构造函数,默认赋值函数以及析构函数,后面两种其实属于,但要需要注意的是,只有当你需要用到这些函数的时候,编译器才会去定义它们。
如果你只是声明一个空类,不做任何事情的话,编译器会自动为你生成一个默认构造函数、一个拷贝默认构造函数、一个默认拷贝赋值操作符和一个默认析构函数。这些函数只有在第一次被调用时,才会别编译器创建。所有这些函数都是inline和public的。
如果你打算在一个“内含引用成员”或者“内含const成员”的类内支持赋值操作,就必须定义自己的默认拷贝赋值操作符。
当基类将自己的默认拷贝赋值操作符声明为private时,子类就不会产生自己的的默认拷贝赋值操作符。因为假如产生了这样的默认拷贝赋值操作符,它无权去调用基类的private部分,
你可以将拷贝构造函数或默认拷贝赋值操作符声明为private。这样明确声明一个成员函数,就阻止了编译器暗自创建的默认版本,而这些函数为private,使得可以成功阻止人们调用它。
上面的做法有一个隐患,因为类自身的member和friend还是可以调用这些private函数。有一个很刁钻的方法,“将成员函数声明为private而且故意不实现它们”,这样既阻止了默认函数的生成,而且如果你试着调用这些函数,就会得到一个链接错误。只声明,不定义,链接器报错。甚至在声明的时候,你连参数也不用写。
而试着将上述的链接器错误提前到编译器也是可以的。我们专门设计一个类Unconpyable。
--------------------------------------------------------------------
class Uncopybale {
protected:
Uncopyable() {}
~Uncopyable() {}
private:
Ucopyable(const Uncopyable&)
Uncopyable& operator=(const Uncopyable&)
};
--------------------------------------------------------------------
为了阻止对象被拷贝,我们唯一需要做的就是继承Uncopyable。这些函数的默认生成版本会尝试调用其基类的对应版本,那些调用会被编译器拒绝,因为它基类的拷贝函数是private。
Boost提供的noncopyable类也有类似的功能。
并不是所有的编译器都包成对象的内置类型成员会被自动初始化为0。永远在使用对象之前先将它初始化。确保每一个构造函数都将对象的每一个成员初始化。 C++规定,对象的成员变量的初始化动作发生在进入构造函数本体之前 对于一些其它类对象,在成员初始化列表中的初始化只是调用了拷贝构造函数一次,而在构造函数内部再为其赋值则在调用默认构造函数后又调用了一次拷贝构造函数。 而对于内置类型 在外内没有太大区别 当然一些const 引用什么的类型肯定不能再类的构造函数内进行初始化 也必须要用成员初始化列表 规定:初始化顺序是基类早于派生类,类成员变量则以其声明顺序为准。所以成员初始化列表中列出的各个成员的顺序最好与声明的顺序相同。 最后说个不常见的问题:某个对象A的非静态成员变量初始化动作正好使用了另外一个编译单元(另外一个cpp)中的某个非静态对象B,你不能保证A在需要B的时候,B就已经被编译好而且产生了。解决的办法是将对象A和对象B都分别放到函数中(貌似是专门为每个这样的对象定制的对象),并且声明为static。这些函数返回的是静态对象的引用。这是单例模式的一种实现。在程序中以前需要对象引用的地方直接调用这些函数就好了。这种reference-returning函数对于处理多线程环境下的“竞速形势(race conditions”的方法是:在程序的单线程启动阶段手工调用所有的reference-returning函数。 参考 http://blog.sina.com.cn/s/blog_5f76aaf20100cwlj.html |
相关文章推荐
- [C++] 关于函数的默认实参
- C++之一些事一些情--函数传参
- C++中的空类,默认产生哪些类成员函数?
- C++中的空类,默认产生哪些类成员函数?
- C++函数的声明,实现和默认实参
- C++中函数的默认参数
- C++注意事项--02 函数指针用于带默认参数的函数
- c++ map的一些基础函数用法
- EffictiveC++之了解c++默认编写并调用那些函数
- C++空类,编译器默认产生的成员函数
- C++空类默认函数(编译器处理)
- C++一些函数 备用
- C++(1)C++类四个默认函数---构造函数、析构函数、拷贝函数、赋值函数
- C++中的空类,编译器默认可以产生哪些成员函数
- Unreal engine 4 C++ 一些调试用的绘制函数
- C++ 一些常用函数的使用(1)
- c++ 函数的默认参数
- 关于C++一些常用函数的说明(scanf,fabs,abs)
- c++空类中默认生成的成员函数
- C++中函数的默认参数