《C++ 特点》

一、特点

1、c++既支持面向过程的程序设计,也支持基于对象和面向对象的程序设计。
2、C语言的结构化和模块化 是面向过程的。c程序的设计者必须细致的设计程序的每一个细节。
3、增加了面向对象的机制。
4、cout cin 是c++系统定义的对象名,称为输入输出流对象。<<  是插入运算符。
5、在一个类中包含两种成员: 数据成员和成员函数。一个类是由一批数据以及对其操作的函数组成的。类可以体现
   数据的封装性和信息隐蔽。
6、由于C语言 没有命名空间,因此用带后缀.h 的头文件时不必用 using namespace std。
7、一般编译系统给出的出错信息分为两种,一种是错误(error)、一种是警告(warning)
8、赋值过程中的类型转换。
10、一个较大的程序不可能完全由一个人 从头至尾地完成,更不可能把所有的内容都放在一个主函数里。把一个大
   程序划分为若干个程序模块(程序文件),编译时以程序文件为单位进行编译。
11、函数重载 和 形参默认值。
12、引用。
13、内置函数。函数的调用需要一定的时间和空间的开销。内置函数在编译时将所调用函数的代码直接嵌入到主调函数
中而不是将流程转出去。
14、函数模板。
15、内部函数和外部函数。   
16、C++预处理功能:宏定义、文件包含、条件编译。
17、c++标准库。
18、字符串类 string。
19、声明一个引用类型的变量时,必须同时使之初始化。
20、动态分配和撤销内存的运算符 new delete。
21、面向对象程序设计:对象 客观存在的任何一样事物都是对象,任何一个对象都具备两个要素,属性和行为。
    可以对一个对象进行封装处理,把它的一部分功能和属性对外界屏蔽。把对象的内部实现和外部行为分隔开来。
22、抽象:抽象的作用是表示同一类事物的本质。类是对象的抽象,对象是类的特例。
23、继承和重用。多态性。
24、面向对象分析、面向对象设计、面向对象编程。
25、类头(class struct ),类体({}) struct 对其成员默认是public ,class 默认是private
26 、类访问限定符 public private protected 。
27、作用域限定符 ::
28、inline 成员函数,如果在类体重不包括循环等控制结构,c++自动将他们作为内置函数来处理。
    如果成员函数不在类体内定义,而在类外定义系统并不把他默认为内置函数。应用inline 做显示声明。
29、类的构造函数。用初始化列表来初始化数据成员。构造函数重载。
30、默认构造函数一个类只能有一个。析构函数:析构函数并不是删除对象,而是在撤销对象占用的内存之前完成一些清理工作
31、指向对象成员的指针。
32、常对象、常成员函数。在定义对象时指定的对象为常对象。常对象必须要有初值。
33、常数据成员:只能通过构造函数的参数初始化表对常数据成员进行初始化。
34、指向对象的常指针,指向常对象的指针。对象的常引用。
35、对象的动态建立和释放。new 和 delete 自动调用构造函数和析构函数。
36、对象的赋值(只是数据成员的赋值)
37、在对象复制过程中代用 拷贝构造函数。当需要用一个已有的对象构造另一个时,当函数参数为类对象时,当返回值类型为类对象时
38、静态数据成员static,静态数据成员是在所有的对象之外单独开辟空间。静态数据成员的初始化需要在类外进行。
39、静态成员函数,调用要用类名::静态成员函数名。静态成员函数没有this 指针。
40、友元函数。friend 可以访问这个类的私有成员。友元成员函数。友元类。
41、类模板。
42、运算符重载。需为 成员函数或者友元函数。重载单目运算符 双目运算符 流插入和流提取运算符。
43、继承和派生。多级派生。
44、派生类构造函数。有子对象派生类的构造函数的写法。多层派生类的构造函数的写法。
45、多重继承。多重继承引起的二义性问题。 虚基类。虚基类的初始化。
46、基类和派生类的转换。
47、继承和组合。是软件重用的两种方式。
48、多态性和虚函数。
49、虚析构函数。
50、纯虚函数和抽象类。
51、输入输出流,文件操作 字符串流。52、异常处理 try catch、命名空间。

二、函数重载

1、重载操作符必须具有一个类类型的操作数

2、形式:友元函数,类的成员函数,作为类成员的操作符重载函数,看起来比友元少了一个参数。作为成员函数的操作符有一个隐形的this形参,限定为第一个操作数。
 
3、如何选择成员或者非成员实现
 
  1》赋值(=)、下标([])、调用(())、剪头(->)等操作符必须定义为成员,定义为成员将在编译时报错
 
  3》"<<" ">>"必须是非成员函数
 
4、重载运算符'>>'函数的第一个参数和返回类型是istream&,第二个参数是要进行输入操作的类;重载"<<"的函数的第一个参数和返回类型是ostream&,第二个参数是要进行输出的操作类。因此只能将<<,>> 定义为非成员函数。 
 
5、转换构造函数
 
6、1》当运算符函数是一个成员函数时,最左边的操作数必须是运算符类的一个类对象或者应用
   2》如果左边的操作数必须是一个不同类的对象,必须作为非成员函数

 

三、类型转换
1、dynamic_cast
1》dynamic_cast是在运行时检查的,用于在继承体系中进行安全的向下转换downcast(当然也可以向上转换,但没必要,因为可以用虚函数实现)
       即:基类指针/引用 -> 派生类指针/引用,如果源和目标没有继承/被继承关系,编译器会报错!
2》dynamic_cast是4个转换中唯一的RTTI操作符,提供运行时类型检查。
3》dynamic_cast不是强制转换,而是带有某种”咨询“性质的,如果不能转换,返回NULL。这是强制转换做不到的。
4》源类中必须要有虚函数,保证多态,才能使用dynamic_cast<source>(expression)

2、static_cast
用法:static_cast < type-id > ( expression )
该运算符把expression转换为type-id类型,在编译时使用类型信息执行转换,在转换执行必要的检测(指针越界,类型检查),其操作数相对是安全的。

3、const_cast

4、dynamic_pointer_cast

 

四、其他

1、volatile的本质:
1> 编译器的优化

在本次线程内, 当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个寄存器中;以后,再取变量值时,就直接从寄存器中取值;当变量值在本线程里改变时,会同时把变量的新值copy到该寄存器中,以便保持一致。

当变量在因别的线程等而改变了值,该寄存器的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致。

当该寄存器在因别的线程等而改变了值,原变量的值不会改变,从而造成应用程序读取的值和实际的变量值不一致。

2>volatile应该解释为“直接存取原始内存地址”比较合适,“易变的”这种解释简直有点误导人。
volatile 影响编译器编译的结果,指出,volatile 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化

嵌入式编程中经常用到 volatile这个关键字,在网上查了下他的用法可以归结为以下两点:

3》告诉compiler不能做任何优化

   比如要往某一地址送两指令: 
   int *ip =...; //设备地址 
   *ip = 1; //第一个指令 
   *ip = 2; //第二个指令 
   以上程序compiler可能做优化而成: 
   int *ip = ...; 
   *ip = 2; 
   结果第一个指令丢失。如果用volatile, compiler就不允许做任何的优化,从而保证程序的原意: 
   volatile int *ip = ...; 
   *ip = 1; 
   *ip = 2; 
   即使你要compiler做优化,它也不会把两次付值语句间化为一。它只能做其它的优化。这对device driver程序员很有用。

4》:表示用volatile定义的变量会在程序外被改变,每次都必须从内存中读取,而不能把他放在cache或寄存器中重复使用。

   如   volatile char a;   
        a=0; 
       while(!a){ 
            //do some things;   
       }   
       doother(); 
   如果没有 volatile doother()不会被执行


【C++智能指针 unique_ptr】

1、unique_ptr 独占所指向的对象, 同一时刻只能有一个 unique_ptr 指向给定对象(通过禁止拷贝语义, 只有移动语义来实现)

2、成员函数
(1) get 获得内部对象的指针, 由于已经重载了()方法, 因此和直接使用对象是一样的.如 unique_ptr<int> sp(new int(1)); sp 与 sp.get()是等价的
(2) release 放弃内部对象的所有权,将内部指针置为空, 返回所内部对象的指针, 此指针需要手动释放
(3) reset 销毁内部对象并接受新的对象的所有权(如果使用缺省参数的话,也就是没有任何对象的所有权, 此时仅将内部对象释放, 并置为空)
(4) swap 交换两个 shared_ptr 对象(即交换所拥有的对象)
std::move(up) 所有权转移(通过移动语义), up所有权转移后,变成“空指针” (up 的定义为 std::unique_ptr<Ty> up)

3、unique_ptr 不支持拷贝和赋值.
  std::unique_ptr<A> up1(new A(5)); 
  std::unique_ptr<A> up2(up1); // 错误, unique_ptr 不支持拷贝
  std::unique_ptr<A> up2 = up1; // 错误, unique_ptr 不支持赋值

虽然 unique_ptr 不支持拷贝和赋值, 但是我们可以调用 release 或 reset 将指针的所有权从一个(非 const) unique_ptr 转移到另一个.
  std::unique_ptr<int> up1(new int(1));
  std::unique_ptr<int> up2(up1.release());

虽然 unique_ptr 不支持拷贝, 但是可以从函数中返回, 甚至返回局部对象. 如下面的代码, 编译器知道要返回的对象即将被销毁, 因此执行一种特殊的"拷贝":
  template <class Ty>
  std::unique_ptr<Ty> Clone(const Ty& obj)
  {
    return std::unique_ptr<Ty>(new Ty(obj));
  }

【C++ typedef typename】

1、那么问题来了,为什么要加上typename关键字?
typedef std::vector<T>::size_type size_type;//why not?
实际上,模板类型在实例化之前,编译器并不知道vector<T>::size_type是什么东西,事实上一共有三种可能:

静态数据成员 
静态成员函数 
嵌套类型
2、那么此时typename的作用就在此时体现出来了——定义就不再模棱两可。

3、C++语言默认情况下,假定通过作用域运算符访问的名字不是类型,所以当我们要访问的是类型时候,必须显示的告诉编译器这是一个类型,通过关键字typename来实现这一点

【c++转换构造函数】

1、应用jsoncpp  
2、原理

class IntClass
{
    private:
        int value;
    public:
        //转换int的转换构造函数
        IntClass(int intValue)
        {
            value = intValue;
        }
        int getValue() const { return value; }
};

由于构造函数 IntClass(int) 只接收一个类型不同于 IntClass 的单个形参,所以它是一个转换构造函数。

只要上下文需要类对象,但提供的却是构造函数形参类型的值,则编译器将自动调用转换构造函数,这会在以下 4 种不同的上下文环境中出现:
该类的一个对象使用转换构造函数的形参类型的值进行初始化。例如:
IntClass intObject = 23;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值