【持续更新】C++里的一些特性

来源:互联网 发布:世界各国软件行业排名 编辑:程序博客网 时间:2024/06/07 17:50

现在从安卓开发转到了后台开发,主要开发语言还是C++,自认为对于C++的了解还是比较少的。C++作为公认的语言特性最多的语言之一,让很多人又爱又恨,包括我在内。喜欢它是因为卓越的性能,讨厌它是由于复杂的语法,这里说复杂是相对而论的,比如Java的语法就比较简单,但对比C而言C++复杂性的优势就体现出来了,它的面向对象和泛型等的特性有力地提高了编程的效率,STL库在平时的开发中基本是必备的,听说大公司都不用STL这玩意,这又是另一说了。很多人推荐使用boost库,但比较可惜的是目前的项目中还没有使用到,有时间可以好好研究下。

前面一段是我对C++的一个简单的印象,那么这篇博文呢主要是记录下C++中的一些容易忽视的语法特性,在开发中我们可能会很少用到,但是这些特性在很多开源的C++项目中用的都比较频繁,了解这些特性对于开发出效率更高的程序或者研读一些优秀的C++开源项目是很有帮助的。同时也欢迎大家对博文中出现的错误提出指正,这样对我而言也是一种成长。


struct vs class

这两者比较大的区别是class默认成员是private,而struct默认成员是public;另外,struct默认继承方式是public,class默认继承方式是private。


new/delete vs operator new/operator delete

new和delete这两个关键字在涉及申请堆内存用的比较多,必须配对来使用的。后者operator new和operator delete在平时的项目中见到的比较少,多了operator这个关键字,operator通常用来重载符号,比如==、!=等。先说下operator new的功能,它是用来申请内存空间,它与new的差别在于,new操作符除了申请内存空间之外,还调用了类的构造函数。类似地,operator delete的功能就是释放内存空间,而delete操作符执行的流程是先调用类的析构函数,再调用operator delete释放内存空间。


placement new

Task* ptask = new (buf) Task; // placement new

placement new我只在STL源码中见到过,应该是在内存管理的那块,它的用法见上面那行代码。这里的buf指的是一段已经申请好的内存空间,它的功能显而易见,就是利用这段已经申请的空间来构造一个对象,它的意义在于不用再次申请内存而是直接使用缓存,省了申请内存空间的时间。


++前缀符和++后缀符重载

看段代码就理解了:

template <class Node>struct node_wrap {Node *ptr;node_wrap(Node* p = 0) : ptr(p) {}Node& operator*() const { return *ptr; }Node* operator->() const { return ptr; }node_wrap& operator++() { ptr = ptr->next; return *this; }node_wrap operator++(int) { node_wrap tmp = *this; ++*this; return tmp; }bool operator==(const node_wrap& i) const { return ptr == i.ptr; }bool operator!=(const node_wrap& i) const { return ptr != i.ptr; }};

注意到的是++前缀返回的是自身的引用,而++后缀返回的是旧的拷贝。这里给我们的提示是++前缀会比++后缀要高效。


explicit

在构造函数中使用,防止隐式转换。


trivial destructor & non-trivial destructor

If a class has no user-declared destructor, a destructor is declared implicitly. 

An implicitly-declared destructor is an inline public member of its class.

A destructor is trivial if it is an implicitly-declared destructor and if all of the direct base classes of its class have trivial destructors and 

for all of the non-static data member of its class that are of class type(or array thereof), each such class has a trivial destructor. Otherwise, 

the destructor is non-trivial.

注:trival翻译为没有用的,non-trivial翻译为有用的


virtual function/class vs pure virtual function/class

A virtual function makes its class a polymorphic base class. Derived classes can override virtual functions. Virtual functions called through base class pointers/references will be resolved at run-time. That is, the dynamic type of the object is used instead of its static type:
Derived d; Base& rb = d; // if Base::f() is virtual and Derived overrides it, Derived::f() will be called rb.f();
A pure virtual function is a virtual function whose declaration ends in =0:
class Base {  // ...  virtual void f() = 0;  // ...
A pure virtual function makes the class it is defined for abstract.Abstract classes cannot be instantiated. Derived classes need to override/implement all inherited pure virtual functions. If they do not, they too will become abstract.
In C++, a class can define a pure virtual function that has an implementation. (What that's good for is debatable.)

purpose of virtual function (from wiki)

The concept of the virtual function solves the following problem:

In object-oriented programming when a derived class inherits from a base class, an object of the derived class may be referred to via a pointer or reference of either the base class type or the derived class type. If there are base class methods overridden by the derived class, the method actually called by such a reference or pointer can be bound either 'early' (by the compiler), according to the declared type of the pointer or reference, or 'late' (i.e. by the runtime system of the language), according to the actual type of the object referred to.

Virtual functions are resolved 'late'. If the function in question is 'virtual' in the base class, the most-derived class's implementation of the function is called according to the actual type of the object referred to, regardless of the declared type of the pointer or reference. If it is not 'virtual', the method is resolved 'early' and the function called is selected according to the declared type of the pointer or reference.

Virtual functions allow a program to call methods that don't necessarily even exist at the moment the code is compiled.

In C++, virtual methods are declared by prepending the virtual keyword to the function's declaration in the base class. This modifier is inherited by all implementations of that method in derived classes, meaning that they can continue to over-ride each other and be late-bound.


caution for virtual destructors

Object-oriented languages typically manage memory allocation and de-allocation automatically when objects are created and destroyed. However, some object-oriented languages allow a custom destructor method to be implemented, if desired. If the language in question uses automatic memory management, the custom destructor (generally called a finalizer in this context) that is called is certain to be the appropriate one for the object in question. For example, if an object of type Wolf that inherits Animal is created, and both have custom destructors, the one called will be the one declared in Wolf.

In manual memory management contexts, the situation can be more complex, particularly as relates to static dispatch. If an object of type Wolf is created but pointed to by an Animal pointer, and it is this Animal pointer type that is deleted, the destructor called may actually be the one defined for Animal and not the one for Wolf,unless the destructor is virtual. This is particularly the case with C++, where the behavior is a common source of programming errors.


difference between private, public and protected inheritance

class A {public:    int x;protected:    int y;private:    int z;};class B : public A{    // x is public    // y is protected    // z is not accessible from B};class C : protected A{    // x is protected    // y is protected    // z is not accessible from C};class D : private A{    // x is private    // y is private    // z is not accessible from D};

0 0