classnode
{
public:
node(){cout<<"constructor node()"<<endl;}
~node(){cout<<"destructor ~node()"<<endl;}
};
classnn
{
public:
node x;
nn(){cout<<"con nn()"<<endl;}
~nn(){cout<<"des ~nn()"<<endl;}
};
intmain()
{
nn a;
return0;
}
几年前的一份C++笔记。
看完了Bruce Eckel的Thing in C++(Volume 1),实践比较少,感觉还是半懂不懂,马上就要【面向对象程序设计】的考试了。考的是C++的东西,做了几份C++的卷子,感觉好多细节的东西还是很不确 定,不敢下手。于是今天把老师的课件翻了出来,整理了一下,做了个小结。虽然感觉很乱,但是对于我自己来说,还是能看懂,很多东西都很显而易见的也写了, 无论怎样,只是为了考试^_^
extern int xx 这是一个声明,而不是定义
在class temp中只定义一个static int b;
1sizeof(temp)=1;这是为什么?
static 变量是这个类共享的,变量是放在全局变量区,不是堆栈里,因此sizeof出来不算在这个static int的大小;是这样的吗??
枚举类型的变量只能进行赋值运算
指针int p,后不能直接进行p = 12这样的赋值,因为指针p没有申请内存
如何解释以下程序?1intmain()
2{
3inta;
4
5a=(int)"string";
6cout<<a<<endl;
7cout<<a<<endl;
8return0;
9}a指向一个string常量的,强制转换为int,因此a还是"string"常量的首地址,*a应该是取前面几位的值
析构函数的调用不一定要大括号
如classnode
{
public:
node(){cout<<"node()"<<endl;}
~node(){cout<<"~node()"<<endl;}
};
intmain()
{
if(1)
node n;
cout<<"out of if"<<endl;
return0;
}输出为
node()
~node()
out of if
另外,一个大括号就是一个scope,不管有没有if,while等语句
if(!cin)
相当于if(cin.fail())
!的运算符在这里被重载了
函数中的static变量在结束main()的时候才释放,但是在全局变量之前
全局变量区:全局变量,静态全局变量,静态本地变量
stack:本地变量
heap:申请的变量,例如,new,malloc
要注意的是new和malloc不能混用
class 中的public表示所有的object都能访问
private只能让类声明的函数和friend函数访问
protected可以子类访问,也可以被friend函数访问
无论是数组还是指针,传到函数中都变为指针
只有在没有构造函数的情况下,编译器才自动分配一个构造函数,否则,只要
编译器看到一个构造函数,就不会生成一个构造函数。
另外,编译器自动生成的构造函数是没有参数的。
根据函数的参数的个数或者类型的不同可以重载函数。
如果只是返回值不同,则不能重载。
缺省参数的函数。缺省值只能从后往前写。
也就是说int f(int i , int j = 0);是可以的。
但是int f(int i = 0 ; int j);是不对的。
一个class中如果有const 常量,声明的时候不能初始化,否则编译器报错
但是如果是static const int a = 0就可以
class中的const int a可以在构造函数中初始化,注意只能在初始化列表中,不能在函数体中赋值
其他的地方定义const 则需要初始化
如果是extern const int a ;就可以不做初始化
内联函数应该放在.h的文件中,因为它是一个声明
另外在class中定义的函数是内联的
1constinta=10;
2inty=a;
是可以的
1constintsize=10;
2inta[size];
是正确的。
但是
1intx=10;
2constintsize=x;
3doubleclassAverage[size];会报错(为什么?)
1constintsize[3]={2,3,4};
2inta[size[0]];
是错的。
也不能这样定义
1structS {inti, j; };
2constS s[]={ {1,2}, {3,4} };
3doubled[s[1].j];
1charconstp="abc";表示p指向的地址是常量,指向的地址不能改变,但是指向的内容可以变
1charconstp="abc";表示p指向的内容是常量,不能改变,但是指向的地址可以改变
1intip;
2constintcip ;//指针可以不初始化
3constintt=3;
4inti;
5ip=&i ;
6ip=&t ;//错误,非常量指针不能指向常量
7cip=&i;
8cip=&t;
9ip=54;
10cip=54;//错误
1chars="hello , world";
是可以的,因为编译器自动转化为
1constchars="hello,world";因此不能再改变s的值了。 但是s指向的地址是可以改变的
voidf(constintx){}
voidg(intx){}
inta=0;
constintb=0;
f(a);
g(b);都是可以的
如果返回值是const,可以赋给non-const,如果不是const 也可以赋给const
如果一个对象定义的时候是const,不能修改这个对象的值
intnode::f()const
函数中不能修改成员变量
也不能调用非常量函数
如
intnode::f(){}
intnode::g()const{f();}是错的。
不能这样定义
classnode
{
private:
constintsize;
inta[size];
};可以把const int 改为static const int
或者用enum来做
引用不能改变
inty , z;
int&x=y;
&x=z;//错误,引用不能改变
intf(int&){}不能调用f(t * 3);
不能这样定义
int&p;但是可以这样
int&p;
引用变量的构造函数中也只能初始化,而不能赋值
如果函数的返回值是const的,就不能做左值
在node a = b;或者node a(b);拷贝构造调用。
当函数返回一个对象的时候,拷贝构造被调用
node f()
{
node x;
returnx;
}在函数的参数中有对象的时候,调用拷贝构造
intf(node x)
{
return1;
}但是如果参数的引用,拷贝构造不被调用
intf(constnode&)
{
return1;
}
静态函数只能对静态变量进行操作
函数中的静态变量只能被初始化一次
static 成员变量在同类的对象中都可见
不能用this来取值
namesapce
可以用using nm::f();
voidmain() {
usingMyLib::foo;
usingMyLib::Cat;
foo();
Cat c;
c.Meow();
}
namespacemy1
{
intf(){cout<<"my1::f()"<<endl;return0;}
intg(){cout<<"my1::g()"<<endl;return0;}
}
namespacemy2
{
intf(){cout<<"my2::f()"<<endl;return0;}
inth(){cout<<"my2::h()"<<endl;return0;}
}
intmain()
{
usingnamespacemy1;
usingnamespacemy2;
f();
g();
h();
return0;
}编译器报错,因为编译器不知道应该调用哪一个f(),
如果不调用f(),编译器就不会报错了。
但是如果将f()变为my1::f()就可以了
注意namespace后面没有";"
【运算符重载】
可以重载的运算符:
+ - * / % ^ & | ~
= < > += -= = /= %=
^= &= |= << >> >>= <<= ==
!= <= >= ! && || ++ --
, -> -> () []
operator new operator delete
operator new[] operator delete[]
不能被重载的运算符
. .:: ?:
sizeof typeid
static_cast dynamic_cast
const_cast renterpret_cast
另外不能重载不存在的运算符,例如*
运算符重载后的优先级不变
所接受的参数的个数也不变
重载为成员函数,可以省略第一个参数,但是
z = x + y;//可以
z = x + 3;//可以
z = 3 + y;//不可以
因为只看第一个参数
但是如果重载为全局函数,以上三个表达式都正确
必须是member function:
= () [] -> ->*
还有一元的运算符必须是member function
所有的二元运算符可以是non-member fuction
函数原型:
+ - * / % ^ & | ~
const T operatorX(const T& l, const T& r);
! && || < <= == >= >
bool operatorX(const T& l, const T& r);
[]
T& T::operator;
++ -- 运算符的重载
constInteger&operator++();//++a
constIntegeroperator++(int);//a++
constInteger&operator--();//--a
constIntegeroperator--(int);//a--在后缀++重载的时候,应该先将原来的对象保存下来用来返回
在调用a++的时候,实际上调用的是a.operator++(0)
//前缀比后缀更加高效
关系运算符的重载
booloperator==(constInteger&rhs )const;
booloperator!=(constInteger&rhs )const;
booloperator<(constInteger&rhs )const;
booloperator>(constInteger&rhs )const;
booloperator<=(constInteger&rhs )const;
booloperator>=(constInteger&rhs )const;
【继承】
输出:
constructor node()
con nn()
des ~nn()
destructor ~node()
在构造函数调用的时候,总是基类先被调用
而析构函数的调用与构造函数的调用是反过来的
如果在子类定义了一个函数与父类的名字相同的话,父类中所有同名的函数被屏蔽
继承后
构造函数,析构函数,operator=,private不能被继承
子类不能访问private的变量,但是可以访问protected的变量
在继承中
class base:derived默认为private继承
class derived:public base
base的public在derived是public,protected在derived是protected,private在derived中被 隐藏
class derived:protected base
base的public在derived是protected,protected在derived是protected,private在 derived中被隐藏
class derived:private base
base的public在derived是private,protected在derived是private,private在derived中被隐 藏
upcasting
base &b = pete;//pete是子类,base是父类
b->f();
调用的是父类的f();
但是如果父类的f()是virtual的话,调用的是子类的f()
voidfunc(Ellipse&elly) {
elly.render();
}
Circle circ(60F);
func(circ);调用的是Circle::render();
但是如果
voidfunc(Ellipse elly) {
elly.render();
}
Circle circ(60F);
func(circ);调用的是Ellipse::render();
析构函数也可以virtual,作用与前面一样
如
base*p=newderived;
delete p;如果析构函数是virtual的,调用的是derived的析构函数,同时也会调用base的
否则调用的只是base的
overriding
可以这样定义:
在base中:virtual base& f();
在derived中:virtual base& f();
但是不能这样定义
在base中:virtual base f();
在derived中:derived f();
当override一个函数的时候,最好重载所有的函数
在构造函数中调用的virtual function是本身的f()
template<classT>
voidswap(T&a , T&b)
{
T temp;
temp=a;
a=b;
b=temp ;
}不能这样调用
inta;
doubleb;
swap(a,b);
template<classT>
voidfoo(){/**/}
foo<int>//此处的T为int
类的模版
template
class node.....
创建对象的时候,可以
node
如果函数不是内联的,在函数的定义的时候,前面要加上
template
template
template
</vector\
也可以是变量
template
可有带有缺省参数
template
模版可以用在继承上
template
class Derived : public List{...};
模版应该放在.h的文件中
【异常】
try{}catch(){}catch{}
catch所有的异常
catch(...);
关于new的异常处理
voidfunc() {
try{
while(1)
{
char*p=newchar[10000];
}
}catch(bad_alloc&e)
{
}
}
还有一些stream的东西还没看。
另外,template和exception的貌似不怎么考,因此比较少T_T 原文链接: https://www.cnblogs.com/vivyli/archive/2010/02/05/1664061.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/7957
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!