const

const指针

 char greeting[] ="hello";
char* p = greeting; // non-const pointer, non-const data
const char* p = greeting; // non-const pointer, const data
char* const p = greeting; // const pointer, non-const data
const char* const p = greeting; //const pointer, const data
 void f1(const Object* o);
void f2(Object const* o);

这两个是一样的;

const vector<int>::iterator更像是T* const;

vector<int>::const_iterator更像是const T*;

enum不能取地址,const可以取地址,define没有任何约束;

const函数是为了可以操作const对象;

 class Test {
public:
void print() const {}
void mut() const { m1 = ; }
private:
mutable int m1; // can be changed even in const functions
};
const Test t;
t.print();
t. mut(); //legal

const版本和非const版本的代码重用。实现const函数,在non-const函数中调用const版本。

 class Test {
public:
const int& operator[](int i) const {...}
int& operator[](int i) {
const_cast<int&>(static_cast<const Test&>(*this)[i]);
}
};

singleton的初始化实现

local static 能够确保在调用时已经初始化。但是仍然不能确保线程安全。所有non-const的static对象,无论它是local还是non-local,在多线程环境下都会有问题。解决的方法就是在一开始的单线程环境下,手动调用这些函数实现初始化。这样可以避免与初始化有关的race conditions。

 class Test {
public:
Test& test() {
static Test t;
return t;
}
};

这种方式仅适用于创建对象;明确是惟一对象时才可使用。

virtual

多态的析构函数,设成virtual,这样在delete的时候才会释放子类的所有资源。

 class Parent {
public:
virtual ~Parent() {...}
};
class Child1: public Parent {};
Parent* p = new Child1;
delete p;

多态的析构函数必须是virtual。

在析构函数里,尽量不要调用会发生异常的操作。如果有,也要提供额外的接口,让用户有机会自己调用处理。

不要在构造函数或析构函数里调用virtual 函数。此时调用virtual函数,调用的是base类的版本。

对于自我实现的类,尽量以pass-by-reference-to-const替换pass-by-value;对于内置类型,以及stl的迭代器和函数对象,尽量以pass-by-value。

调用父类函数:

 class child1 : public Parent {
public:
virtual void print() {
Parent::print();
}
};

同名遮掩

 class Parent {
public:
void t1(int) {}
void t1() {}
};
class Child1 : public Parent {
public:
void t1() {}
};
class Child2 : public Parent {
public:
using Parent::t1;
void t1() {}
};
Child1 c1;
c1.t1(); // error
Child2 c2;
c2.t1(); // right

不使用using,父类的重载函数会被子类所遮掩,看不到了。

  • 如果派生类的函数与基类的函数同名,但是参数不同。此时,若基类无virtual关键字,基类的函数将被隐藏。(注意别与重载混淆,虽然函数名相同参数不同应称之为重载,但这里不能理解为重载,因为派生类和基类不在同一名字空间作用域内。这里理解为隐藏)
  • 如果派生类的函数与基类的函数同名,但是参数不同。此时,若基类有virtual关键字,基类的函数将被隐式继承到派生类的vtable中。此时派生类 vtable中的函数指向基类版本的函数地址。同时这个新的函数版本添加到派生类中,作为派生类的重载版本。但在基类指针实现多态调用函数方法时,这个新的派生类函数版本将会被隐藏。
  • 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏。(注意别与覆盖混淆,这里理解为隐藏)。
  • 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数有virtual关键字。此时,基类的函数不会被“隐藏”。(在这里,你要理解为覆盖哦^_^)

template

嵌套的类型名称,是需要在修饰符前加上typename的。

 template<typename C>
void print(const C& c) {
typename C::const_iterator iter(c.begin());
/* ... */
}

这里只能用typename,不能用class。

编译细节

 class A {
public:
void print() {cout << "a" << endl;}
}; int main(int argc, char** argv) {
A* pa = ;
pa->print(); return ;
}

这样的代码会core吗?不会,其实编译之后相当于print(A* this), 这时传入一个0,函数里面没有用,所以不会发生段错误。

类型转换

dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。
在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;
在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。

dynamic_cast运算符可以在执行期决定真正的类型。如果 downcast 是安全的(也就说,如果基类指针或者引用确实指向一个派生类对象)这个运算符会传回适当转型过的指针。如果 downcast 不安全,这个运算符会传回空指针(也就是说,基类指针或者引用没有指向一个派生类对象)。

dynamic_cast要求父类必须有虚函数。static_cast会在编译期就告诉你能不能转。

class D {
};
class E: public D {
};
int main(int argc, char** argv) {
D* d = new E();
E* e = static_cast<E*>(d);
E* f = dynamic_cast<E*>(d);
return ;
}

这里D没有一个虚函数,所以会输出:

 t.cpp: In function ‘int main(int, char**)’:
t.cpp::: error: cannot dynamic_cast ‘d’ (of type ‘class D*’) to type ‘class E*’ (source type is not polymorphic)
E* f = dynamic_cast<E*>(d);

如果:

 int main(int argc, char** argv) {
D* d = new D();
E* e = static_cast<E*>(d);
E* f = dynamic_cast<E*>(d);
cout << (f ? "addr" : "null") << endl;
return ;
}

从D转到E,这样dynamic_cast会返回null。

如果:

int main(int argc, char** argv) {
E* e = new E();
D* d = static_cast<D*>(e);
D* f = dynamic_cast<D*>(e);
cout << d << endl;
cout << f << endl;
cout << (f ? "addr" : "null") << endl;
return ;
}

从E上行转D的话,static_cast和dynamic_cast是一样的,打印出来的地址都是一样的。

delete和delete[]

正确的应该是new和delete对应,new[]和delete[]对应。

 E* e = new E();
delete e;
D* d = new D[];
delete[] d;

如果,

 E* e = new E();
delete[] e;

编译同样通过了,但是也是会core dump。

如果,

 D* d = new D[];
delete d;

编译是通过了,但是会报错,指针出错。

*** Error in `./t': munmap_chunk(): invalid pointer: 0x0000000001e8c038 ***
Aborted (core dumped)

C++盲点的更多相关文章

  1. C语言 malloc()与sizeof运算的盲点

    //malloc()与sizeof运算的盲点 #include <stdio.h> #include <stdlib.h> #include <string.h> ...

  2. 【PHP代码审计】 那些年我们一起挖掘SQL注入 - 8.全局防护盲点的总结下篇

    0x01 背景 现在的WEB应用对SQL注入的防护基本都是判断GPC是否开启,然后使用addlashes函数对单引号等特殊字符进行转义.但仅仅使用这样的防护是存在很多盲点的,接上篇http://www ...

  3. 【PHP代码审计】 那些年我们一起挖掘SQL注入 - 7.全局防护盲点的总结上篇

    0x01 背景 现在的WEB应用对SQL注入的防护基本都是判断GPC是否开启,然后使用addlashes函数对单引号等特殊字符进行转义.但仅仅使用这样的防护是存在很多盲点的,比如最经典的整型参数传递, ...

  4. [置顶] NS2中TCP拥塞控制仿真过程中盲点解析

    最近利用NS2做TCP拥塞控制协议的仿真,发现很多变量的方法含义都是解释的不清楚,给核心模块修改带来很多麻烦,所以决定用最准确的语言解释成员变量.方法,术语等的含义.限于个人水平,若有错误请留言指正! ...

  5. C语言盲点笔记1

    寥寥数笔,记录我的C语言盲点笔记,仅仅为以前经历过,亦有误,可交流. 1.int* a和int *a有差别吗? 没有不论什么差别,都表示a是int指针 建议这么写int *a;这样明显一点 理由例如以 ...

  6. NSRunLoop原理详解——不再有盲点

    编程最怕的就是有盲点,不确定,而runloop官网对其提及的又很少:那么看完这篇应该使你有底气很多~ RunLoop整体介绍 An event-processing loop, during whic ...

  7. OC方法交换swizzle详细介绍——不再有盲点

    原文链接:https://www.cnblogs.com/mddblog/p/11105450.html 如果对方法交换已经比较熟悉,可以跳过整体介绍,直接看常见问题部分 整体介绍 方法交换是runt ...

  8. 细数EDM营销中存在的两大盲点

    国庆节了,祝大家国庆快乐,转眼博客至今已有三年了.下面博主为大家介绍EDM营销中存在的两大盲点,供大家参考. 一是忽略用户友好.用户友好策略是Email营销成功的关键要素,具体包括内容友好策略.方式友 ...

  9. java基础盲点梳理

    类的基本成员才有默认值 finalize()并非析构,Java中没有析构,使用finalize()通常在于跨语言调用情景:比如使用C进行malloc内存分配以后,要在finalize()方法中进行fr ...

  10. 【前端盲点】DOM事件流论证CSS盒模型是否具有厚度

    前言 很久没有扯淡了,我们今天来扯淡吧. 我今天思考了一个问题,我们页面的dom树到底是如何渲染的,而CSS盒模型与javascript是否有联系,于是便想到一个问题: CSS的盒模型具有厚度么??? ...

随机推荐

  1. 2.django笔记之缓存,session,cookie,ajax

    一.django缓存 1.缓存 缓存的意义在于把昂贵的计算结果保存起来一遍下次的访问,有缓存的站点的流程大概是这样子的: 给定一个url,检查页面是否在缓存中 如果在,返回缓存的页面 否则,生成该页面 ...

  2. 解决 mysql 启动报错--发现系统错误2,系统找不到指定的文件

    HKEY_LOCAL_MACHINE-SYSTEM-CurrentControlSet-services-mysql(服务名)-ImagePath 更改为(自己的):"C:\Program ...

  3. Android实现电子邮箱客户端

    本文主要讲述了安卓平台上利用QQ邮箱SMTP协议,POP3协议发送与接收消息的实现 发送邮件核心代码 import java.security.Security; import java.util.D ...

  4. 用java程序打印菱形

    代码如下

  5. poj 2019 二维rmq *

    题目大意:给出一个N*N矩形,每个格子上有一个价值.询问一个b*b的矩形在左上角的位置(x,y),(x+b-1,y+b-1)这一部分的最大值-最小值是多少. 模板题 #include <stdi ...

  6. JAVA 正则表达式、汉字正则、 java正则代码

    转自于:http://blog.csdn.net/q326527970/article/details/7513974 (一)字母.数字.下划线.汉字正则表达式 1. 只有字母.数字和下划线且不能以下 ...

  7. 导入/导出Excel

    --从Excel文件中,导入数据到SQL数据库中,很简单,直接用下面的语句:/*============================================================ ...

  8. codeforces 385 c

    Description Recently, the bear started studying data structures and faced the following problem. You ...

  9. Kali Linux 2016.2初体验使用总结

    Kali Linux 2016.2初体验使用总结 Kali Linux官方于8月30日发布Kali Linux 2016的第二个版本Kali Linux 2016.2.该版本距离Kali Linux  ...

  10. IE6/IE7中display:inline-block解决办法

    IE6/IE7下对display:inline-block的支持性不好. 1.inline元素的display属性设置为inline-block时,所有的浏览器都支持: 2.block元素的displ ...