文档章节

c++学习

y
 yizhangxyz
发布于 2016/01/31 15:20
字数 3297
阅读 77
收藏 0
点赞 1
评论 0
  1. const Base b,const Base *pb,一旦声明为const,所有非const成员函数都不能调用了,因为这样可能修改成员变量。public成员变量可以访问,但是不能赋值。

  2. virtual关键字默认继承。构造函数不能定义为虚函数,因为对象构造完成之前,虚表尚未建立,这时候虚函数没意义。析构函数不能定义为纯虚函数,因为在删除派生类的时候会先调用子类的析构函数,再调用父类的析构函数,如果父类析构函数未定义,那么找不到符号会编译出错。

  3. 函数的new ,delete运算符也可以重载。

    void* operator new(size_t size)

    void operator delete(void *memblock),但是注意当类有虚析构函数的时候,delete必须有实现体

  4. 复制构造函数传入的参数必须是引用或者常引用。因为传入副本的话,复制副本的过程会导致无限递归。

  5. struct {int x; int y; int z}Point;

    Point* pPoint = NULL;

    int offset = (int)(&(pPoint)->z);

    结论:offset == 8。&(pPoint)->z表示取point中z的地址。pPoint地址是0,所以加上偏移量8,z的地址就是8.并不需要point的实际地址。改方法可用来求一个变量在对象中的偏移量

     

  6. 结构体也可以有private成员,并且可以继承。它和class的主要区别是它的的成员默认是public的。

  7. 类的函数地址并不存放在对象中,所以在调用成员函数的时候,并不需要对象的地址。但是在访问成员变量的时候需要this指针。

    class A{

    int value;

    public:

    void print1(){cout<<"print1";};

    void print2(){cout<<value;};

    }

    测试:A* a = nullptr; a->print1();a->print2();

    结果:print1正常打印,因为在调用函数的时候把对象的this传递给函数,但在print1并未使用到

    print2崩溃,因为用到this的value变量

  8. 数组和指针的区别

    a、 修改数据的区别:如果指针指向的是常量,那么不能修改数据。
    char* c = "abc";
    c[0] = 'd';//运行时会报错

    b、 sizeof数组得到的是数组的长度,sizeof指针得到的是指针变量的长度,通常是4个字节

  9. overload(重载)和overide(覆盖)overwrite(重写)

    重载表示函数方法名相同,但是参数表不同。c++通过参数表构建函数的全名

    覆盖表示子类重写父类的函数,函数名和参数必须相同,父类函数加上virtual。

    重写表示子类遮掩父类的方法,通常子类函数名和父类相同,但是参数不同。或者参数相同,但是父类没有加上virtual。

  10. delete 和delete[]区别:

    delete[]表示删除数组,并且调用数组每个元素的析构函数,对于基础类型,2个方法没有区别

  11. 引用作为函数返回值的注意事项

    a 临时变量不能作为返回值。因为临时变量会被销毁

    b new 出来的对象也不能作为返回值,因为函数的返回值往往作为一个临时变量来使用,所以导致new分配的内存无法跟踪,导致内存泄漏

    c 类的成员变量可以作为返回值,但最好是const?

  12. 数组的引用与引用的数组

    数组可以有引用,int a [] = {1,1}; a的引用为 int (&b) [2]= a;

    不可以有引用的数组。因为引用是别名,不暂用存储空间。但是数组用连续空间存储变量,所以不能有引用的数组

  13. volatile。表示获取变量的时候都从地址获取。如果没有这个变量则可能优化为从寄存器中获取。可从java学习笔记里面学习。

  14. #ifdef __cplusplus

    extern "C" {

    #endif

    xxxxx

    #ifdef __cplusplus

    }

    #endif

    extern "C":告诉c++编译器,xxxxx是c风格写的代码

  15. 可以通过继承模板单例类来实现单例

    template <typename T>
    class SingleTon{
    public:
        static T *getInstance(){
            static T instance;
            return &instance;
        }
    };

    class A :public SingleTon<A>{
        friend class SingleTon<A>; //class A的构造函数私有。不加上友元的话,父类无法构造子类
    private:
        A(){
        }
    };
    A::getInstance();

  16. RTTI 运行时类型信息,运行时识别对象信息,c++只记录类的名字和继承关系链。

    class Base{};

    class Derived : public Base{
    };

    class Base1{
        virtual void test(){};
    };

    class Derived1 : public Base1{
    };

    Derived d;
    Base& b = d;
    const type_info& typeinfo = typeid(b);
    CCLOG("name=======%s",typeinfo.name());//输出Base
        
     Derived1 d1;
     Base1& b1 = d1;
     const type_info& typeinfo1 = typeid(b1);
     CCLOG("name1=======%s",typeinfo1.name());//输出Derived1

    注意当是指针或者父类赋值没有使用引用的时候下面会输出Base1。RTTI的信息据说存放在虚函数表里。没有虚表的对象不能进行转换。

     

    16.c++ 的类和结构体一样也是需要字节对齐的。类的大小和变量声明顺序有关。

class Test1{
    int a;
    char b;
    int c;
    char d;
};

class Test2{
    int a;
    int c;
    char b;
    char d;
};

经测试,上面2个类的size分别是16和12.

17.public和private继承(is 和has的关系)。public继承认为派生类是基类。而private继承则认为派生类不是基类,他只是使用基类的方法(effective c++)。可用下面的方法测试:

class Base{
};

class Derived1 :public Base{
};

class Derived2 :private Base{
};

Base *b1 = new Derived1(); //ok
Base *b2 = new Derived2();//错误,无法赋值

Derived1 *d1 =  new Derived1();
Derived2 *d2 =  new Derived2();
void test(Base* b){}
test(d1);
test(d2);//这句话编译不通过。

18.以下情况只能用intializationlist 而不能用assignment:
a、const、reference 成员变量 
b、基类的构造函数

19.i++ 和++i的区别:

//i++实现代码为:
int operator++(int)
{
    int temp = *this;
    ++*this;
    return temp;
}

// ++i实现代码为:
int& operator++()
{
    *this += 1;
    return *this;
}//返回自身引用

20. c++ stl中的list是双向链表。因为他可以通过iterator和reverse_iterator来正向和反向遍历。

21.stl中的map采用的是平衡二叉树,通常是红黑树来实现查找。

22.由于list和map都使用链式结构,所以节点在内存中的位置不会发生变化。所以在insert后iterator(指向节点的指针)不会失效。而vector是数组,在insert后iterator就失效了。

22. deque和vector差不多,看起来像是连续空间,但实际上他是由多个连续空间组成的。所以并不存在数据的整体移动。并且他可以在数据的前后两端进行插入和移除。

23.stack是先进后出的,单向开口的。stack只能push和pop,没有遍历的功能,因此没有提供迭代器。deque和list都是双向开口的,因此可通过这2种数据结构来实现stack。

24.queue是先进先出的,后端进,前端出,没有遍历的功能,因此没有提供迭代器。

25.static变量不会占用对象存储空间。const 变量父子对象各有自己的存储。

26.mutable关键字解决const函数不能修改non-static成员变量的限制。

27.inline:inline只是对编译器的申请,而非强制行为。

  • 将函数声明为inline,不一定真的inline,如果函数体过大,编译器是拒绝的。

  • inline函数内部有对virtual函数调用也不行,因为inline函数的替换是在编译时期的,但是编译期无法知道函数对应实体

  • 未声明为inline的函数编译器也可能将他当作inline处理。如下:

    class A{
    int a;
    public:
    int get(){return a;} //这里是inline的隐式声明
    };

28.模板(编译器多态)。

函数模板

template <class T>
void swapValue(T& a, T& b)
{
    T c = b;
    b = a;
    a = c;
}

类模板

template<class T>
class Base
{
public:
    T1 a;
    void test1(){}
    void test2(){}
};

模板特化

template<>
class Base<ClassA>
{
public:
    void test1(){}
};

继承模板

template<class T>
class Derived1 :public Base<T>
{
public:
    void test1()
    {
        test();//这里会报错,因为模板可能进行特化,所以这里并不清楚base类是否有这个方法
    }
};
三种办法解决上面的问题。
(1)this->test();//特指base class templates内的成员名称
(2)using Base<ClassA>::test;
(3)Base<ClassA>::test();

29.初始化列表。成员变量初始化顺序和初始化列表里面的顺序无关,和class里面的声明顺序有关。

class Base
{
private:
    int m_i,m_j;
public:
    Base(int i):m_j(i),m_i(m_j){}
};

比如这样会导致m_i初始化错误。
初始化列表在构造函数之前执行。

30.虚继承。class 派生类名:virtual 继承方式  基类名

为了解决从不同途径继承来的同名的数据成员在内存中有不同的拷贝造成数据不一致问题,将共同基类设置为虚基类。这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数名也只有一个映射。这样不仅就解决了二义性问题,也节省了内存,避免了数据不一致的问题。

class Base  
{
 public:  
 Base(){} 
 void print(){cout << "Base print" <<endl;}  
};

class Mid1 : virtual public Base  
{
public:  
Mid1(){}  
};

class Mid2 : virtual public Base  
{
 public:  
 Mid2(){}  
};

 class Child:public Mid1, public Mid2  
{
 public:  
 Child(){}  
};

 

如果Mid1,Mid2不加virtual,只能像下面那样使用

d.Mid1::print();
d.Mid2::print();

加了,就可以这样使用d.print();

 

31.多继承类型转换

class Top
{ public: int a;
};
class Left : virtual public Top
{ public: int b;
};
class Right : virtual public Top
{ public: int c;
};
class Bottom : public Left, public Right
{ public: int d;
};

Bottom *b = new Bottom();
    
Left *l = b;
Right *r = b;

注意l和r的值不同

32.stl map和set的区别。

二者都采用红黑树来存放数据

map(映射):存放的是key和value,key不能重复,但是value可以重复

set(集合)  :存放key(key就是value),key不能重复

33.

class A{
    
public:
    A(){
      std::cout << "default construc A"<< std::endl;
    }
    A(int i){
        std::cout << "construc A 1"<< std::endl;
    }
};

A a=1;和A a(1);都是执行的A(int i)构造函数
记住调用无参数构造函数的时候不能 A a(),只能A a;A a();表示名称为a的函数声明。

34.当基类的虚函数为private的时候,也会存放在虚表中,如果子类重写了基类的虚函数。同样具有多态效果。比如:

class Base
{
public:
    void Open()
    {
        OnOpen();
    }
private:
    virtual void OnOpen() = 0;
};

class Derived : public Base
{
public:
   
private:
    void OnOpen()
    {
        cout << "Derived OnOpen----------" << endl;
    }
};

Base *pBase = new Derived();
pBase->Open();//输出Derived OnOpen----------

35 NULL和nullptr区别在于,前者只是一个宏定义,后者是一个真正的类型。应该优先使用nullptr。

36.c++ 构造函数不能互相调用。但是java是可以的。通过this(X,X,X);

37.函数重载
void test(){}   
void test(int a=0){}
调用test的时候会编译报错。调用是模棱两可的。构造函数也是一样的。

38.初始化列表和构造函数类赋值区别在于,构造函数内赋值之前肯定已经经过初始化列表。初始化列表内调用的是构造函数,而构造函数内调用的是拷贝运算符。

39.private变量
class MyString
{
private:
    char *m_data;
public:
    void test(const MyString &another){
        m_data = new char[strlen(another.m_data)+1];
    }
};

在类的方法内可以访问本类其他对象的private成员。java也是一样的。

40.priority_queue:优先队列

priority_queue<Type, Container, Functional>
其中Type 为数据类型, Container 为保存数据的容器,Functional 为元素比较方式。
Container 必须是用数组实现的容器,比如 vector, deque 但不能用 list.
STL里面默认用的是 vector. 比较方式默认用less (operator<), 所以如果你把后面俩个参数缺省的话,
优先队列就是大顶堆,队头元素最大。

priority_queue<int, vector<int>, greater<int> >pq;//greater 和less已经实现了

41.数组名和数组名取地址

数组名和数组名取地址在数值上是相同的,均表示数组第一个元素的地址。但是二者的颗粒度不同。
        当数组是一维数组时,数组名是以一个数组元素为颗粒度,表现为“当数组名加1时,这里的1表示一个数组元素单元”,例子中的数组元素为整数,所以数组名加1时地址加4;而数组名取地址&以整个数组为颗粒度,表现为“当数组名取地址&加1时,这里的1是表示整个数组单元”,例子中的数组为有5个元素的整型数组,所以数组名取地址&加1时,地址加20.
       当数组是二维数组时,数组名array、array[0]、&array[0][0]以及数组名取地址&在数值上是相同的,同样各个之间的颗粒度不同。其中array[0]以及 &array[0][0] 的颗粒度相同,均是以一个数组元素为颗粒度,所以它们加1后,地址加4;而数组名和数组名取地址&颗粒度不同,前者以一行元素为颗粒度,后者以整个数组单元为颗粒度,所以前者加1,地址加3*4,后者加1,地址加6*4.

总结一下:数组名取地址加1移动的是整个数组的长度。
                  二维数组数组名加1移动一行

42.Concurrency::concurrent_queue:高效线程安全队列。

© 著作权归作者所有

共有 人打赏支持
y
粉丝 1
博文 57
码字总数 42366
作品 0
成都
C语言/C++程序员编程学习自信心曲线图

C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到...

小辰带你看世界 ⋅ 05/10 ⋅ 0

C语言/C++永远都不会过时的编程语言

C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到...

小辰带你看世界 ⋅ 03/30 ⋅ 0

Java程序员如何高效而优雅地入门C++

Java程序员如何高效而优雅地入门Cpp,由于工作需要,需要用C++写一些模块。关于C++ 的知识结构,虽说我有过快速学习很多新语言的经验,但对于C++ 我也算是老手,但也还需要心生敬畏,本文会从...

小欣妹妹 ⋅ 04/23 ⋅ 0

C语言/C++编程学习强势之处的体现

C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到...

小辰带你看世界 ⋅ 05/12 ⋅ 0

C语言/C++编程学习未来之路

C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到...

小辰带你看世界 ⋅ 03/30 ⋅ 0

大神有话说之c++,还在迷茫的朋友可以来看一下

C++ 是一种中级语言,它是由 Bjarne Stroustrup 于 1979 年在贝尔实验室开始设计开发的。C++ 进一步扩充和完善了 C 语言,是一种面向对象的程序设计语言。C++ 可运行于多种平台上,如 Window...

悟空_b201 ⋅ 05/30 ⋅ 0

当年自学c++的时候走了很多弯路,今天分享给大家学习经验

本人从事c++ 将近6年的时间,今天给大家分享下学习经验 到今年年底结束,我做c++ 开发已经6年的时间了,现在月薪可以接近三万已经算知足了,但是距离我年薪百万的目标还有很长的路要走,而以...

你的社交帐号昵 ⋅ 05/30 ⋅ 0

VS2010/MFC编程入门教程之目录和总结(鸡啄米)

鸡啄米的这套VS2010/MFC编程入门教程到此就全部完成了,虽然有些内容还未涉及到,但帮助大家进行VS2010/MFC的入门学习业已足够。以此教程的知识为基础,学习VS2010/MFC较为深入的内容已非难事...

weixin_40647819 ⋅ 05/23 ⋅ 0

C语言/C++编程新手学习常见问题

C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到...

小辰带你看世界 ⋅ 05/11 ⋅ 0

C语言编程学习项目实战:图书管理系统

C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到...

小辰带你看世界 ⋅ 06/04 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

来自一个优秀Java工程师的简历

写在前面: 鉴于前几天的一份前端简历,虽然带着很多不看好的声音,但却帮助了很多正在求职路上的人,不管评论怎么说,我还是决定要贴出一份后端的简历。 XXX ID:357912485 目前正在找工作 ...

颖伙虫 ⋅ 19分钟前 ⋅ 0

Confluence 6 恢复一个站点有关使用站点导出为备份的说明

推荐使用生产备份策略。我们推荐你针对你的生产环境中使用的 Confluence 参考 Production Backup Strategy 页面中的内容进行备份和恢复(这个需要你备份你的数据库和 home 目录)。XML 导出备...

honeymose ⋅ 今天 ⋅ 0

JavaScript零基础入门——(九)JavaScript的函数

JavaScript零基础入门——(九)JavaScript的函数 欢迎回到我们的JavaScript零基础入门,上一节课我们了解了有关JS中数组的相关知识点,不知道大家有没有自己去敲一敲,消化一下?这一节课,...

JandenMa ⋅ 今天 ⋅ 0

火狐浏览器各版本下载及插件httprequest

各版本下载地址:http://ftp.mozilla.org/pub/mozilla.org//firefox/releases/ httprequest插件截至57版本可用

xiaoge2016 ⋅ 今天 ⋅ 0

Docker系列教程28-实战:使用Docker Compose运行ELK

原文:http://www.itmuch.com/docker/28-docker-compose-in-action-elk/,转载请说明出处。 ElasticSearch【存储】 Logtash【日志聚合器】 Kibana【界面】 答案: version: '2'services: ...

周立_ITMuch ⋅ 今天 ⋅ 0

使用快嘉sdkg极速搭建接口模拟系统

在具体项目研发过程中,一旦前后端双方约定好接口,前端和app同事就会希望后台同事可以尽快提供可供对接的接口方便调试,而对后台同事来说定好接口还仅是个开始、设计流程,实现业务逻辑,编...

fastjrun ⋅ 今天 ⋅ 0

PXE/KickStart 无人值守安装

导言 作为中小公司的运维,经常会遇到一些机械式的重复工作,例如:有时公司同时上线几十甚至上百台服务器,而且需要我们在短时间内完成系统安装。 常规的办法有什么? 光盘安装系统 ===> 一...

kangvcar ⋅ 昨天 ⋅ 0

使用Puppeteer撸一个爬虫

Puppeteer是什么 puppeteer是谷歌chrome团队官方开发的一个无界面(Headless)chrome工具。Chrome Headless将成为web应用自动化测试的行业标杆。所以我们很有必要来了解一下它。所谓的无头浏...

小草先森 ⋅ 昨天 ⋅ 0

Java Done Right

* 表示难度较大或理论性较强。 ** 表示难度更大或理论性更强。 【Java语言本身】 基础语法,面向对象,顺序编程,并发编程,网络编程,泛型,注解,lambda(Java8),module(Java9),var(...

风华神使 ⋅ 昨天 ⋅ 0

Linux系统日志

linux 系统日志 /var/log/messages /etc/logrotate.conf 日志切割配置文件 https://my.oschina.net/u/2000675/blog/908189 logrotate 使用详解 dmesg 命令 /var/log/dmesg 日志 last命令,调......

Linux学习笔记 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部