C++程序设计课程的总结,方便以后快速查阅和复习
函数名是函数的入口地址,指向函数的指针称为“函数指针”。
比如,qsort库函数:
void qsort(void *base, int nelem, unsigned int width,
int ( * pfCompare)( const void *, const void *));
其中的第四个参数,就是一个函数指针,pfCompare:比较函数的地址。
int main(int argc, char *argv[]){
...
}
argc:命令行参数的个数
argv:指针数组,argv[0]指向第一个命令行参数,argv[1]指向第二个命令行参数...
& | │ | ^ | ~ | << | >> |
---|---|---|---|---|---|
按位与 | 按位或 | 按位异或 | 按位非 | 左移 | 右移 |
异或运算实现a,b值交换:
a = a ^ b;
b = b ^ a;
a = a ^ b;
变量的引用,等价于这个变量,相当于一个别名:
int n = 4;
int &r = n;
在定义前加上const关键字,就代表这是个常量(常量,常量指针,常引用),不可变的东西。
const int *p = &n; //常量指针
用new分配内存,delete释放内存
分配变量:
int * p = new int;
* p = 5;
delete p;
分配数组:
int * p = new int[20];
p[0] = 1;
delete [ ] p;
缺省参数:定义函数时,让最右边的几个参数有缺省值,这样在调用的时候相应位置可以不写参数。
void func( int x1, int x2 = 2, int x3 = 3) { }
关键字:private,public,protected,缺省为私有成员
用来复制的构造函数,这样一个参数:同类对象的引用
Complex( const Complex & c ) {...} //可以没有const
和类型转换函数不是一个名词的样子,这个类型转换构造函数,其实就是一个构造函数而已,但是像具有类型转换的功能,把其他的东西转换为本类,比如:
Complex(int i){
real = i; imag = 0;
}
~String();
delete pTest; delete [] pTest;
封闭类里包含了其他的类的对象,所以生成封闭类对象时,应该也要知道里边的对象该怎么初始化
在定义封闭类的构造函数时,添加初始化列表:
CMyClass::CMyClass(int x, int y) : m_y(y), m_x(m_y){...}
调用顺序:
友元函数:在一个类里边,用friend加到前面来声明一个函数(这个函数可以是另一个类的成员函数),这个函数就是该类的友元函数,可以访问该类的私有成员
class A { friend void B::function(); };
友元类:声明一个类是本类的友元,那么那个类的成员函数都可以访问本类的私有成员
class A { friend class B; };
指向成员函数当前所作用的对象
静态成员函数不能使用this指针,因为静态成员函数并不具体作用于某个对象
常量对象:不希望这个对象被修改,在前面加const关键字
const Demo Obj;
常量成员函数:在成员函数说明后面加const关键字,它不能修改其所作用的对象,所以它不能修改成员变量的值。也不能调用同类的非常量成员函数(静态成员变量和静态成员函数除外,因为静态的东西不算某个对象所自有)
(有const的和没const的函数,其他一样,算重载)
void Sample::Get Value() const
常引用:不能通过常引用修改其引用的变量,在前面加const关键字
void Printf Obj( const Sample & o)
函数的参数需要传递对象的时候,直接传递对象需要调用复制构造函数,效率低,所有可以用引用(或指针),但是这样有危险(函数有可能一不小心对引用的对象进行修改),所以呢就加一个const,这样的话一旦想修改就会编译错误了
重载为普通函数
Complex operator+ (const Complex & a, const Complex & b) {
return Complex( a.real+b.real, a.imaginary+b.imaginary);
}
这时,仅仅是对 '+' 这个运算符的功能进行了扩充,参数个数还是本身的运算符目数重载为成员函数
Complex Complex::operator+(const Complex & operand2) {
return Complex( real + operand2.real, imaginary + operand2.imaginary );
} // 在类里边还得声明,或者直接在类中定义,这样就是类的成员函数了
这时,参数个数为本身的运算符目数减一,因为现在执行这个成员函数的对象本身不需要放在参数里面了
比如:
将一个字符串复制给另一个字符串,直接使用“=”,算是浅复制(指向字符串的指针之间的复制),我们可以重载“=”实现深复制(指针所指向的字符串内容间的复制)
返回值可以是 String &,这样会比较方便
有时,成员函数不能满足使用要求,普通函数又不能访问类的私有成员,这时可以重载为友元
cout << 5 << "abc"
这种写法是因为在iostream里对“<<”进行了重载
自增自减本来都是一元运算符,重载时为了区分吧,然后前置运算符作为一元运算符重载T operator++();
,后置运算符作为二元运算符重载T operator++(int);
,仅仅只是表面上多一个参数。
int可作为一个类型强制转换运算符被重载:
operator int(){ return n;}
,然后就能这些写了:(int) s;
等效于s.int()
class 派生类名: public 基类名{...};
派生类对象的体积,等于基类对象的体积,再加上派生类对象自己的成员变量的体积。在派生类对象中,包含着基类对象,而且基类对象的存储位置位于派生类对象新增的成员变量之前。
void derived::access() {
j = 5;//error(派生类没有变量j)
i = 5; //引用的是派生类的 i
base::i = 5; //引用的是基类的 i
func(); //派生类的
base::func(); //基类的
}
派生类的成员函数可以访问当前对象的基类的保护成员
FlyBug :: FlyBug (int legs, int color, int wings): Bug(legs, color) {
n Wings = wings;
}
如果是public(其他不行):
b = d;
base &br = d;
base *pb = & d;
虚函数
class base {
virtual int get() ;
};
int base::get() //函数声明时加virtual就行
{ }
多态的表现形式1:
通过基类指针调用基类与派生类中同名的虚函数时,
若,指针指向的是基类对象,则调用基类的虚函数
若,指向的是派生类的对象,则调用派生类虚函数
多态的表现形式2:
用基类引用来实现,和上面的基本一样
多态的好处:增强程序的可扩充性
比如,很多的类都继承于同一个基类,它们有一些类似的操作,需要使用这些类的对象们,如果没有多态,那么代码的每一个语句都需要具体到哪个类,这样需要写很多类似的重复性代码,增加新的类时很不方便,而使用多态的话,不需要在类的代码里明确到底是对那个类对象进行操作,全都使用基类指针或引用,实际使用时让这个指针指向谁就操作谁, 这样就方便多了。
“多态”的关键在于通过基类指针或引用调用一个虚函数时,编译时不确定到底调用的是基类还是派生类的函数,运行时才确定 —— 这叫“动态联编”。
多态的函数调用语句被编译成一系列根据基类指针所指向的(或基类引用所引用的)对象中存放的“虚函数表”的地址,在虚函数表中查找虚函数地址,并调用虚函数的指令。
如果不是虚的析构函数,那么使用基类指针删除派生类对象时,只调用基类的析构函数,这样派生类对象实际上还没被删掉。所以我们这样:把基类的析构函数声明为virtual(这时派生类的析构函数就自动也是虚函数了),这时使用基类指针删除派生类对象,会首先调用派生类的析构函数,然后调用 基类的析构函数。
virtual void Print() = 0;
ofstream out File(“clients.dat”, ios::out|ios::binary); //打开文件
out 删除原有内容, app 在尾部添加 binary 以二进制格式ofstream fout; fout.open( “test.out”, ios::out|ios::binary );
if(!fout) { cerr << “File open error!”<<endl; }
fout.write( (const char *)(&x), sizeof(int) );
fin.read( (char *)(&x), sizeof(int) );
比如,交换两个变量的值,编译器会根据调用的情况生成相应数据类型的函数
template <class T>
void Swap(T & x, T & y) {
T tmp = x;
x = y;
y = tmp;
}
编译器先找普通函数,再去找模板函数,再找实参自动类型转换后能匹配的普通函数,如何还找不到就报错
Pair类模板:
template <class T1, class T2>
class Pair{
public:
T1 key; //关键字
T2 value; //值
Pair(T1 k,T2 v):key(k),value(v) { };
bool operator < (const Pair<T1,T2> & p) const;
};
template<class T1,class T2>
bool Pair<T1,T2>::operator<( const Pair<T1, T2> & p) const {
return key < p.key;
}
Pair类模板的使用
int main() {
Pair<string, int> student("Tom",19); //实例化出一个类 Pair<string, int>
cout << student.key << " " << student.value;
return 0;
}
template <class T, int elements Number>
非类型参数: 用来说明类模板中的属性类模板与继承:
类模板派生出类模板,模板类派生出类模板,普通类派生出类模板,模板类派生出普通类
string s1("Hello");
string s2(8, 'x');
string month = "March";
s = 'n'
s.length()
getline(cin, s);
s2 = s1;
s3.assign(s1);
s3.assign(s1, 1, 3);
s2[5] = s1[3] = 'a';
s1 += s2;
s1.append(s2);
int f1 = s1.compare(s2);
s2 = s1.substr(4,5);
s1.swap(s2);
freopen("test.txt","w",stdout); //将标准输出重定向到 test.txt文件
freopen(“t.txt”,“r”,stdin); //cin被改为从 t.txt中读取数据
while(cin>>x){...}
istream & getline(char * buf, int buf Size);
istream & getline(char * buf, int buf Size,char delim);
if(!cin.getline(…))
p = find(v.begin(),v.end(),3);
返回一个迭代器,指向找到的元素,或者last可变长动态数组,#include <vector>
,所有STL算法都支持
vector();
vector(int n);
vector(int n, const T & val);
vector(iterator first, iterator last);
成员函数 | 作用 |
---|---|
void pop_back(); |
删除容器末尾的元素 |
void push_back(const T & val); |
将val添加到容器末尾 |
int size(); |
返回容器中元素的个数 |
T & font(); |
返回容器中第一个元素的引用 |
T & back(); |
返回容器中最后一个元素的引用 |
list<T> classname
classname.sort(compare);
classname.sort();
若一个类重载了运算符“()”,则该类的对象就成为函数对象
以下模板可以用来生成函数对象:equal_tp,greater,less ...头文件
lst.sort(greater<int>()); //greater<int>()是个对象
template<class Key, class Pred = less<Key>, class A = allocator<Key> >
class multiset { …… };
template<class Key, class Pred = less<Key>, class A = allocator<Key> >
class set { … }
template<class Key, class T, class Pred = less<Key>,class A = allocator<T> >
class multimap { …...pedef pair<const Key, T> value_type; …….}; //Key 代表关键字的类型
template<class Key, class T, class Pred = less<Key>,class A = allocator<T> >
class map { ….typedef pair<const Key, T> value_type; …….};//关键字(first)各不相同
用某种顺序容器来实现,让已有的顺序容器以栈/队列的方式工作,stack,queue,priority_queue
STL算法大致可以分为一下七类:
iterator min_element(iterator first, iterator last);
iterator min_element(iterator first, iterator last, Pred op);//表达式op(x, y)的返回值来判断x与y的大小
template<size_t N>
class bitset{ ...... };
比如
作者:rubbninja
出处:http://www.cnblogs.com/rubbninja/
关于作者:目前主要研究领域为机器学习与无线定位技术,欢迎讨论与指正!