指针既可以操作指针所指向的内存地址,亦可以操作指针所指向的值;
文件打开失败判断:ofstream ifstream 打开失败对象为假,打开成功为真
if(file)
{
}
ifstream 每次读取都是一行;
如果以追加的方式使用fstream (ios_base::in | ios_base::app)打开文件,文件的位置是末尾,
函数入口每次都必须对传入参数的合理性判断;
函数在有返回值的情况下,必须在每个可能退出点上返回值;
c++ 不允许引用改变其应引用的值;从一而终;
const 引用;
指针和引用
在使用指针时必须先判断其值非零;引用则不需要;
函数默认值建议放置在函数声明而非定义处;
#include<limits>
numeric_limits<int>::max(); //取最大值;
inline 函数一般定义在头文件中,inline函数一般在编译期间就进行了展开,执行期间不存在函数调用,inline函数一般是体积小,常被调用,从事计算不复杂;
重载函数只可以是参数不一样,不能一返回值不一样来区分;当我们调用函数不需要返回值的时候,就没得办法区分
const object 一处文件其他文件便不可见;
每次使用指针的时候,需要考虑指针越界;
const_iterator
vector 和deque 都是一块连续的内存;vector 在元素的尾端插入和删除都是很快的;deque在容器的前后插入和删除都很快;
#include<algorithm> //算法
find() //查找无序集合
banary_search()//查找有序集合,查询的集合必须排序
count()//返回数值相符的元素数目
search()//从一个集合内查找子集
copy()//集合复制;必须确保目的容器有足够容量;
函数对象; 就是重载了operator()的class
#include<funtion>
plus<type> ,minus<type>,negate<type>,mutiplise<type>,divides<type>,moudles<type>
less<type>,less_equal<type>,greater<type>,greater_equal<type>,equal_to<type>,not_equal<type>
logic_and<type>,logic_or<type>,logic_not<type>
adaptor适配器:
bind1st 绑定2元函数的第一个参数
bind2st 绑定2元函数的第二个参数;
not1是构造一个与谓词结果相反的一元函数对象
not2是构造一个与谓词结果相反的二元函数对象
几元就是有几个参数,1个参数叫1元,2个参数叫2元;
插入迭代器,使用算法函数式需要传入一个目的迭代器,前提传入的迭代器必须有足够的空间,使用 iterator insertor迭代器则不需要提供足够容量;
#include<iterator>
back_inserter()
inserter();
front_inserter(); //copy(vec.begin(),vec.end,front_inserter(dst_vex))
输入输出迭代器
输入输出迭代器
iostream iterator
vector<string> vec;
istream_iterator<string> in(cin);
istream_iterator<string> eof;
copy(in,eof,back_inserter(vec);
ostream_iterator<string> out;
copy(vec.begin(),vec.end(),out);
class 内部定义的函数一般会认为是inline函数;
每个类是否需要拷贝构造函数和赋值函数;
如果类中存在const成员函数,那就必须在声明和实现中都指定const;
如何给类定义一个迭代器:
class Test_iterator
{
private:
list<int>::iterator it;
//T x;
//list<int>::iterator i;
public:
Test_iterator(list<int>::iterator i):it(i)
{
}
Test_iterator& operator++()//前置++
{
it++;
return *this;
}
Test_iterator& operator++(int)//后置++
{
it++;
return *this;
}
Test_iterator& operator--()
{
it++;
return *this;
}
int & operator*()
{
return *it;
}
bool operator==(const Test_iterator &a)
{
return it == (a.it);
}
bool operator!=(const Test_iterator &a)
{
return it != (a.it);
}
};
class Test
{
private:
mutable int x;
list<int> li;
//const int x;
public:
typedef Test_iterator itrator;
void set_x(int a) const;
void push_back(int a)
{
li.push_back(a);
}
list<int>::iterator begin()
{
return li.begin();
}
list<int>::iterator end()
{
return li.end();
}
};
int mian()
{
Test t;
t.set_x(3);
t.push_back(1);
t.push_back(2);
t.push_back(3);
t.push_back(4);
Test::itrator it(t.begin());
for (auto it = t.begin(); it != t.end(); it++)
{
cout << *it << endl;
}
}
静态绑定:编译时确定调用的实例
动态绑定:执行期间才知道调用的实例;
静态函数不可以声明为虚函数;
含有储纯虚函数的类不可以定义实例变量,必须有子类派生,并且子类实现其虚函数,才可以定义实例对象;
抽象基类的析构函数一定要定义为虚函数,主要是放置内训泄露;
{
//这种情况就会出问题
parent *p = new child()
delete p;
}
在类外定义虚函数时不需要指定virtual
当基类的虚函数返回每个基类的形式(通常是引用或者时指针),派生类的重载同名函数就可以返回派生类的形式,这种形式不影响多态调用;
class base{
virtual base & copy()
{
cout << "child copy" << endl;
return *this;
}
}
class child:public base{
virtual child & copy()
{
cout << "child copy" << endl;
return *this;
}
}
基类的构造函数内部不要调用虚函数,因为子类的数据成员还未定义,可能会发生未定义行为;
RTT
typeid(*this).name() //返回类名称;#include<typeinfo> typeid 返回一个type_info对象;
支持 == 比较 if(typeid(*this) ==typeid(child)){ }
异常的一网打尽的方法(3个点) try{}catch(...){}
C++ 规定异常必须处理,否则程序调用reiminate()结束进程;