1.讲一下类的private和protected的区别
private 是完全私有的,只有当前类中的成员能访问到.
protected 是受保护的,只有当前类的成员与继承该类的类才能访问.
2、gdb常用命令有什么
l@ubuntu:~/c c++/fast_sort/gdb$ gcc -g hello2.c -o hello
l@ubuntu:~/c c++/fast_sort/gdb$ gdb hello
GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from hello...done.
(gdb) list
1 #include<stdio.h>
2
3 int main() {
4 int a = 1, b = 2, c = 3;
5 int i;
6 printf("hello chenyu");
7 for (i = 0 ; i < 100; i++) {
8 ++a;
9 if (i > 90) {
10 ++b;
(gdb)
11 } else {
12 ++c;
13 }
14 }
15 printf("a = %d, b = %d, c = %d", a, b, c);
16 int cc = 0;
17 for (cc; cc < 9; cc++) {
18 printf("c %d", i);
19 }
20 return 0;
(gdb)
21 }
(gdb) b 10
Breakpoint 1 at 0x68b: file hello2.c, line 10.
(gdb) b 18
Breakpoint 2 at 0x6c4: file hello2.c, line 18.
(gdb) start
Temporary breakpoint 3 at 0x652: file hello2.c, line 4.
Starting program: /home/l/c c++/fast_sort/gdb/hello
Temporary breakpoint 3, main () at hello2.c:4
4 int a = 1, b = 2, c = 3;
(gdb) c
Continuing.
Breakpoint 1, main () at hello2.c:10
10 ++b;
(gdb) watch b
Hardware watchpoint 4: b
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/l/c c++/fast_sort/gdb/hello
Breakpoint 1, main () at hello2.c:10
10 ++b;
(gdb) watch b
Hardware watchpoint 5: b
(gdb) watch b
Hardware watchpoint 6: b
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/l/c c++/fast_sort/gdb/hello
Breakpoint 1, main () at hello2.c:10
10 ++b;
(gdb) watch b
Hardware watchpoint 7: b
(gdb) watch b
Hardware watchpoint 8: b
(gdb) watch b
Hardware watchpoint 9: b
(gdb)
3、Linux里面要查看cpu占用率要怎么做
[root@sss ~]# top
top - 16:54:38 up 7 days, 5:13, 3 users, load average: 0.00, 0.01, 0.05
Tasks: 77 total, 2 running, 75 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.7 us, 0.3 sy, 0.0 ni, 99.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1882232 total, 813020 free, 330164 used, 739048 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 1386608 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
17215 root 0 -20 127504 12176 9560 S 0.7 0.6 21:46.45 AliYunDun
2770 root 20 0 573932 17232 6088 S 0.3 0.9 1:11.38 tuned
1 root 20 0 43548 3844 2588 S 0.0 0.2 0:06.54 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:08.75 ksoftirqd/0
5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H
... ...
4、什么是虚函数
5、C++多态怎么实现的(当基类的指针指向派生类的对象时,对指针虚拟函数的调用实际上是调用了派生类的虚拟函数)
6、纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但是要求任何派生类都要定义自己的实现方方法。在基类中实现纯虚函数的方法是在函数原型后面加“=0”,如:
virtual void funtion1()=0
简单地说,那些被virtual关键字修饰的成员函数,就是虚函数。
虚函数的作用,用专业术语来解释就是实现多态性。
在基类的派生类中就可以通过重写虚拟函数来实现对基类虚拟函数的覆盖。
当基类的指针指向派生类的对象时,对指针虚拟函数的调用实际上是调用了派生类的虚拟函数。这是面向对象中多态性的体现。
#include<iostream>
using namespace std;
class A
{
public:
void print()
{
cout<<"This is A"<<endl;
}
};
class B : public A
{
public:
void print()
{
cout<<"This is B"<<endl;
}
};
int main()
{
//为了在以后便于区分,我这段main()代码叫做main1
A a;
B b;
a.print();
b.print();
return 0;
}
/结果
This is A
This is B
//
int main()
{
//main2
A a;
B b;
A *p1 = &a;//&放在右侧表示取地址
A *p2 = &b;
p1->print();
p2->print();
return 0;
}
/结果
This is A
This is A
这明显不是我们需要的结果,而如果我们采用虚函数,将类改动一下,如下:
class A
{
public:
virtual void print()
{
cout<<"This is A"<<endl;
}
};
class B : public A
{
public:
void print()
{
cout<<"This is B"<<endl;
}
};
结果
This is A
This is B
这就是多态。
当基类A的指针p2指向派生类的对象时b,对指针虚拟函数的调用实际上是调用了派生类B的虚拟函数
7、C++中基类的析构函数为什么要用virtual虚析构函数
using namespace std;
class ClxBase{
public:
ClxBase() {};
~ClxBase() {cout << "Output from the destructor of class ClxBase!" << endl;};
void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
};
class ClxDerived : public ClxBase{
public:
ClxDerived() {};
~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };
void DoSomething() { cout << "Do something in class ClxDerived!" << endl; };
};
int main(){
ClxDerived *p = new ClxDerived;
p->DoSomething();
delete p;
return 0;
}
Do something in class ClxDerived!
Output from the destructor of class ClxDerived!
Output from the destructor of class ClxBase!
派生类的指针指向派生类的对象,delete析构过程是先释放继承类,再释放基类。
这段代码中基类的析构函数不是虚函数,在main函数中用继承类的指针去操作继承类的成员,释放指针P的过程是:先释放继承类的资源,再释放基类资源.
#include<iostream>
using namespace std;
class ClxBase{
public:
ClxBase() {};
~ClxBase() {cout << "Output from the destructor of class ClxBase!" << endl;};
void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
};
class ClxDerived : public ClxBase{
public:
ClxDerived() {};
~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };
void DoSomething() { cout << "Do something in class ClxDerived!" << endl; }
};
int main(){
ClxBase *p = new ClxDerived;
p->DoSomething();
delete p;
return 0;
}
Do something in class ClxBase!
Output from the destructor of class ClxBase!
基类指针指向派生类对象,delete只释放基类资源
这段代码中基类的析构函数同样不是虚函数,不同的是在main函数中用基类的指针去操作继承类的成员,释放指针P的过程是:只是释放了基类的资源,而没有调用继承类的析构函数.调用 dosomething()函数执行的也是基类定义的函数.
一般情况下,这样的删除只能够删除基类对象,而不能删除子类对象,形成了删除一半形象,造成内存泄漏.
在公有继承中,基类对派生类及其对象的操作,只能影响到那些从基类继承下来的成员.如果想要用基类对非继承成员进行操作,则要把基类的这个函数定义为虚函数.
析构函数自然也应该如此:如果它想析构子类中的重新定义或新的成员及对象,当然也应该声明为虚的.
using namespace std;
class ClxBase{
public:
ClxBase() {};
virtual ~ClxBase() {cout << "Output from the destructor of class ClxBase!" << endl;};
virtual void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
};
class ClxDerived : public ClxBase{
public:
ClxDerived() {};
~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };
void DoSomething() { cout << "Do something in class ClxDerived!" << endl; };
};
int main(){
ClxBase *p = new ClxDerived;
p->DoSomething();
delete p;
return 0;
}
Do something in class ClxDerived!
Output from the destructor of class ClxDerived!
Output from the destructor of class ClxBase!
虚函数:基类指向派生类;delete的时候基类析构是virtual的,就会先找到派生类析构再执行基类析构
这段代码中基类的析构函数被定义为虚函数,在main函数中用基类的指针去操作继承类的成员,释放指针P的过程是:只是释放了继承类的资源,再调用基类的析构函数.调用dosomething()函数执行的也是继承类定义的函数.
如果不需要基类对派生类及对象进行操作,则不能定义虚函数,因为这样会增加内存开销.当类里面有定义虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间.所以,只有当一个类被用来作为基类的时候,才把析构函数写成虚函数.
因此当一个类被用来当作基类的时候才会把析构函数写成虚函数。
8、 动态链接库和静态链接库的区别
动态链接是只建立一个引用的接口,而真正的代码和数据存放在另外的可执行模块中,在运行时再装入;
静态链接是把所有的代码和数据都复制到本模块中,运行时就不再需要库了
静态连接库就是把(lib)文件中用到的函数代码直接链接进目标程序,程序运行的时候不再需要其它的库文件;动态链接就是把调用的函数所在文件模块(DLL)和调用函数在文件中的位置等信息链接进目标程序,程序运行的时候再从DLL中寻找相应函数代码,因此需要相应DLL文件的支持。