C++学习(30)
来源:互联网 发布:java 北京尚学堂视频 编辑:程序博客网 时间:2024/06/06 03:43
1.全局变量如果加上static关键字,就相当于各自文件的本地全局变量。如果不加static,链接时会出错。
全局变量可以定义在可被多个.c文件包含的头文件中。
2.下列for循环的循环体执行次数为:0
for(int i=10,j=1;i=j=0;i++,j--)
分析:i=j=0;是一个赋值语句,位于for的判断位置,就只当成条件真假,C中0为假,非0为真,
所以i=j=0,结果就是i=0,为假,则循环不进入;
如果是 i=j=1,结果就是真,可以进入循环,并且无限。
3.下列程序输出结果:
#include<iostream>#include<string.h>using namespace std;int main() { chara[10]={'1','2','3','4','5','6','7','8','9',0},*p;int i; i=8; p=a+i; printf("%s\n",p-3);}
分析:1)、p指向a[5]
2)、“%s”输出直到'\0'的字符串
3)、最后的0为数字而非字符‘0’,ASIIC码中0为空字符
所以输出的结果是6789而不是67890
4. 在《C++primer》说过如果子类没有显示地调用父类的构造方法,则默认地调用父类的不带参数的构造方法,这里父类定义了带参数的构造方法,则默认构造函数失效了,需要显式地调用父类的构造方法。
当基类构造函数需要外部传递参数才能进行初始化时,派生类必须显式定义构造函数,为基类传递参数;基类如果不需要传递或者可以不传递参数,派生类可以不用显式定义构造函数。
5.
#include<iostream>#include<string.h>usingnamespace std;intmain() { int a[3]; a[0]=0,a[1]=1,a[2]=2; int *p,*q; p=a; q=&a[2]; cout<<p<<""<<q<<endl; cout<<q-p<<endl;}
分析:可以先想想指针指示数组时,移动的情况, 类比得到指针加减其实是加减的类型的字节的大小。
所以:指针 ptr的类型是 int*, 它指向的类型是 int ,它被初始化为指向整形变量 a 。接下来的第 3 句中,指针 ptr 被加了 1 ,编译器是这样处理的:它把指针 ptr 的值加上了 sizeof(int) ,在 32 位程序中,是被加上了 4。
单独打印p和q都会显示地址,但是加减运算就会变成以指针类型(这里是整型)为基本单位的加减运算。1个整型就是1。
6.在基类和派生类中,派生类可以定义其基类中不具备的数据和操作。对两个有相同名字的数据成员进行访问时,如果没有作用域分隔符限定时,对此数据成员的访问将出现歧义。
7.有如下程序:
#include<iostream>#include<string.h>using namespace std;class A{public: int _a; A(){ _a=1; } void print() { cout<<_a; }}; class B:public A { public: int _a; B() { _a=2; }};int main() { B b; b.print(); cout<<b._a;}
分析:因为在继承的时候,允许子类存在与父类同名的成员变量,但是子类屏蔽父类的同名成员变量,他们同时存在。 因为给孩子类中没有定义print函数,所以会按照就近原则去寻找父类中是否有print函数。恰好父类中有这个函数,于是调用父类的print函数b.print(),而这个函数会调用父类的a变量。
8.
#include<iostream>#include<string.h>using namespace std;int main() { int b; char c[10]; scanf("%d%s",&b,c);//scanf("%d%s",&b,&c);都是一样的。}
9.在64位系统下,根据如下程序,输出结果为:80 8
#include<iostream>#include<string.h>using namespace std;int main() { char *p[10]; char (*p1)[10]; cout<<sizeof(p)<<""<<sizeof(p1);}
分析:重点理解p跟谁结合了,跟[]结合,则p就是一个数组;跟*结合,p就是一个指针;
首先[]()的优先级一样,均大于*
char *p[10],p与[]结合,所以p就是一个数组,数组的元素比较特殊,是指针,指针大小为8,所以是10*8=80;
char(*p1)[10],与*结合,所以是一个指针,大小为8
分析二:
char *p[10]是指针数组,数组里存放了10个指针,在64位系统下指针占8个字节,所以sizeof(p)=10*8=80.
char(*p1)[10]是数组指针,p1是一个指向存放10个char类型的数组的指针,所以sizeof(p1)=8.
10.JAVA没有指针的概念,被封装起来了,而C++有;
JAVA不支持类的多继承,但支持接口多继承;C++支持类的多继承;
C++支持操作符重载,JAVA不支持;
JAVA的内存管理比C++方便,而且错误处理也比较好;
C++的速度比JAVA快。
C++更适用于有运行效率要求的情况;JAVA适用于效率要求不高,但维护性要好的情况。
11.在linux+gcc下,关于以下代码正确:ABD
#include<iostream>#include<string.h>using namespace std;std::string& test_str() { std::stringstr="test"; return str;}int main() { std::string&str_ref=test_str(); std::cout<<str_ref<<std::endl; return 0;}
A编译警告 B返回局部变量引用,运行时出现未知错误
C正常编译且运行 D把代码中的&号都去掉,程序正常运行
分析:引用返回的是局部变量本身,而不是复制一份再返回,所以结果难以预料;
其次返回局部自动变量是可以的,只要不是地址或引用就可以,否则需要将变量声明成static类型。
c++中string是一个类,去掉&后return时会调用复制构造函数,因此是可以得到所要的内容。
12.
#include<iostream>#include<string.h>using namespace std;int main() { inta[10]={0,1,2,3,4,5,6,7,8,9},*p=a; cout<<*p<<endl; cout<<p[6]<<""<<*(a+6)<<" "<<*(p+6)<<""<<p+6<<endl; return 0;}
分析:p[6]、*(a+6)、*(p+6)是一个意思; a+6与p+6是一个意思,都是取地址。
13.使用char *p=new char [100]申请一段内存,然后使用delete p释放,会有声明问题?
不会有内存泄露,但不建议用。
分析:C++告诉我们在回收用 new 分配的单个对象的内存空间的时候用 delete,回收用new[]分配的一组对象的内存空间的时候用delete[]。
关于new[]和delete[],其中又分为两种情况:(1) 为基本数据类型分配和回收空间;(2) 为自定义类型分配和回收空间。
基本类型的对象没有析构函数,所以回收基本类型组成的数组空间用delete和delete[]都是应该可以的;但是对于类对象数组,只能用delete[]。
所以一个简单的使用原则就是:new和delete、new[]和 delete[]对应使用。
点击打开链接
14.面向对象的五大基本原则:
单一职责、开放封闭、里氏替换、依赖倒置、接口隔离
五个基本原则:
单一职责原则(Single-ResposibilityPrinciple):一个类,最好只做一件事,只有一个引起它的变化。单一职责原则可以看做是低耦合、高内聚在面向对象原则上的引申,将职责定义为引起变化的原因,以提高内聚性来减少引起变化的原因。
开放封闭原则(Open-Closed principle):软件实体应该是可扩展的,而不可修改的。也就是,对扩展开放,对修改封闭的。
Liskov替换原则(Liskov-Substituion Principle):子类必须能够替换其基类。这一思想体现为对继承机制的约束规范,只有子类能够替换基类时,才能保证系统在运行期内识别子类,这是保证继承复用的基础。
依赖倒置原则(Dependecy-InversionPrinciple):依赖于抽象。具体而言就是高层模块不依赖于底层模块,二者都同依赖于抽象;抽象不依赖于具体,具体依赖于抽象。
接口隔离原则(Interface-SegregationPrinciple):使用多个小的专门的接口,而不要使用一个大的总接口
15.
#include<iostream>#include<string.h>using namespace std;struct st_t{ int status; short *pdata; char errstr[32];};int main() { st_t st[16]; char *p=(char*)(st[2].errstr+32); //第3个的errstr字符串+32后是第4个结构体的首指针 cout<<sizeof(st_t)<<endl; //sizeof(st_t)是40 printf("%d",(p-(char*)(st))); //p减去第0个指针就求4-0中间有多少字节,就是40*3=120
16.
auto fn=[](unsigned char a) { cout<<std::hex<<(int)a<<endl; }; fn(-1);
分析:-1=1000 0001
存储的是补码形式
①反码是1111 1110【符号位不变,其他位取反】
②补码是1111 1111【反码加1】
然后std::hex以十六进制显示【1111 1111】
17.抽象类的指针可以指向不同的派生类。
用关键字virtual修饰的成员函数叫做虚函数,虚函数是为了实现多态而存在的,必须有函数体;
纯虚函数的声明,是在虚函数声明的结尾加0,没有函数体。在派生类中没有重新定义虚函数之前是不能调用的;
如果一个类中至少含有一个纯虚函数,此时称之为抽象类。所以抽象类一定有纯虚函数;
基类类型的指针可以指向任何基类对象或派生类对象;
- [C学习]函数(?)
- C#(WINFORM)学习
- C学习(2)
- 学习资源(C++)
- C++&C学习笔记(一)(基础)
- Linux-GCC学习(C/C++)
- C指针学习(Pointers in C)
- 学习C语言的相关网站(C学习资料)
- 学习C语言的相关网站(C学习资料)
- 如何学习C++(经典)
- [C学习]总结(数据类型)
- ---------------C#(.NET)学习步骤---------
- C++test 学习(一)
- C++test 学习(二)
- C++test 学习(三)
- C++test 学习(四)
- C++test 学习(五)
- C#_WinForm学习(1)
- No1031.Campus
- 购物车模块系统的开发
- 获取微信openid
- Openssl 之大数运算函数 BN
- 通用Dialog避免IllegalArgumentException
- C++学习(30)
- python27,anaconda2 安装网络绘图工具igraph及cairo
- 关于zookeeper错误KeeperErrorCode = ConnectionLoss的问题
- vs自带查看动态库dll信息的工具
- ios 遮罩层 全屏显示(有的时候导航栏会遮挡) 引导 --新手笔记
- 【Linux】解决用vi修改文件,保存文件时,提示“readonly option is set”
- plsql的注释
- sysfs方式控制GPIO
- java创建对象的几种方式