文章目录

  • 1. 面向对象的三大特征
  • 2. 简述多态实现原理
  • 3. 怎样解决菱形继承
  • 4. C++ 11中function lambda bind之间的关系
  • 5. 继承下的构造函数和析构函数的执行顺序
  • 6. 虚函数表和虚函数表指针(vptr)的创建时机
  • 7. 虚析构函数的作用
  • 8. 智能指针种类以及使用场景
  • 9.C++ 11用过哪些新特性
  • 10.动态库与静态库区别
  • 11.左值引用与右值引用的区别?右值引用的意义?
  • 参考

1. 面向对象的三大特征

2. 简述多态实现原理


demo1:早绑定

#include <iostream>using namespace std;class Base {public:void func() {cout << "Base::func" << endl;}
};class Drive : public Base {public:void func() {cout << "Drive::func" << endl;}
};int main() {Base *pbase1 = new Base();Base *pbase2 = new Drive();pbase1->func();pbase2->func();return 0;
}

运行结果

Base::func
Base::func

demo2:晚绑定

#include <iostream>using namespace std;class Base {public:virtual void func() {cout << "Base::func" << endl;}
};class Drive : public Base {public:void func() {cout << "Drive::func" << endl;}
};int main() {Base *pbase1 = new Base();Base *pbase2 = new Drive();pbase1->func();pbase2->func();return 0;
}

运行结果

Base::func
Drive::func

demo3:晚绑定原理

#include <iostream>using namespace std;class Base {public:virtual void func() {cout << "Base::func" << endl;}
};class Drive : public Base {public:void func() {cout << "Drive::func" << endl;}
};int main() {typedef void (*Func)(void);Base *pbase1 = new Base();Base *pbase2 = new Drive();long * vptr1 = (long *)*(long *)pbase1;Func f1 = (Func)vptr1[0];f1();long * vptr2 = (long *)*(long *)pbase2;Func f2 = (Func)vptr2[0];f2();// pbase1->func();// pbase2->func();return 0;
}

运行结果

Base::func
Drive::func

3. 怎样解决菱形继承


demo1

#include <iostream>using namespace std;class A {public:void func1() {}void func2() {}int num;
};class B1 : public A {public:void func1() {}
};class B2 : public A {public:void func2() {}
};class C : public B1, public B2 {};int main() {C c{};c.B1::num = 1;c.B2::num = 2;cout << "c.B1::num " << c.B1::num << " c.B2::num " << c.B2::num << endl;return 0;
}

运行结果:
会造成二义性

c.B1::num 1 c.B2::num 2

demo2:
如何解决菱形继承?带上virtual关键字

#include <iostream>using namespace std;class A {public:void func1() {}void func2() {}int num;
};class B1 : virtual public A {public:void func1() {}
};class B2 : virtual public A {public:void func2() {}
};class C : public B1, public B2 {};int main() {C c{};c.B1::num = 1;c.B2::num = 2;cout << "c.B1::num " << c.B1::num << " c.B2::num " << c.B2::num << endl;return 0;
}

运行结果

c.B1::num 2 c.B2::num 2

打印类的继承关系和虚表结构。
GCC7.x 以前使用选项:-fdump-class-hierarchy
GCC8及以后使用选项:-fdump-lang-class

  • 未使用虚继承类的继承关系和虚表结构 。可以看出两个A的地址不一样。

  • 使用虚继承类的继承关系和虚表结构 。可以看出两个A的地址一样。B1 B2均会指向相同的虚表,反向查找A的地址。

4. C++ 11中function lambda bind之间的关系


demo1:

#include <functional>
#include <iostream>
#include <algorithm>using namespace std;void hello(int count) {cout << "hello world: " << count << endl;
};class StaticFunc {public: static void hello(int count) {cout << "StaticFunc::hello world: " << count <<endl;}
};class Hello {public:void operator() (int count) {i += count;cout << "Hello::hello world: " << i << endl;}void operator() (int a, int b) {cout << "Hello::hello world: a + b = " << a + b << endl;}int i = 0;
};class CHello {public:void hello(int count) {cout << "CHello::hello world: " << count <<endl;}
};class LambdaHello {public:LambdaHello(int _i) : i(_i) {}void operator() (int count) {i ++;cout << "LambdaHello::hello world: " << count << " i = " << i << endl;}
private:int i;
};class BindHello {public:BindHello(function<void(int)> _fn, int _count) : fn(_fn), count(_count) {}void operator()() {fn(count);}
private:function<void(int)> fn;int count;};class BindCHello {public:typedef void (CHello::*Fn)(int);   BindCHello(Fn _fn, CHello *_c) : fn(_fn), c(_c) {}void operator() (int count) {(c->*fn)(count);}
private:Fn fn;CHello *c;
};int main() {function<void(int)> f_hello1 = hello;f_hello1(1);function<void(int)> f_hello2 = &hello;f_hello2(1);function<void(int)> f_hello3 = &StaticFunc::hello;f_hello3(2); function<void(int)> f_hello4 = Hello();f_hello4(4);f_hello4(4); // 可以通过成员变量i 来存储状态function<void(int, int)> f_hello5 = Hello();f_hello5(5, 6);function<void(CHello *, int)> f_hello6 = &CHello::hello; //保存类的成员函数 CHello c;f_hello6(&c, 7);int i = 0;auto f_hello7 = [i](int count) mutable -> void {i ++;cout << "lambda::hello world: " << count << " i = " << i << endl;}; // 创建了一个闭包 f_hello7(8);cout << " i = " << i << endl; // i依然为0 auto f_hello8 = [&i](int count) -> void {i ++;cout << "lambda::hello world: " << count << " i = " << i << endl;};  f_hello8(8);cout << " i = " << i << endl; // i的值改变为1auto f_hello9 = LambdaHello(i);f_hello9(9);auto f_hello10 = bind(&hello, 10);f_hello10();// 绑定类成员函数auto f_hello11 = bind(&CHello::hello, &c, 11);f_hello11();// 提供占位符auto f_hello12 = bind(&CHello::hello, &c, placeholders::_1);f_hello12(1000);auto f_hello13 = BindHello(&hello, 10);f_hello13();auto f_hello14 = BindCHello(&CHello::hello, &c);f_hello14(10000);return 0;
}

运行结果:

hello world: 1
hello world: 1
StaticFunc::hello world: 2
Hello::hello world: 4
Hello::hello world: 8
Hello::hello world: a + b = 11
CHello::hello world: 7
lambda::hello world: 8 i = 1i = 0
lambda::hello world: 8 i = 1i = 1
LambdaHello::hello world: 9 i = 2
hello world: 10
CHello::hello world: 11
CHello::hello world: 1000
hello world: 10
CHello::hello world: 10000

5. 继承下的构造函数和析构函数的执行顺序


demo1

#include <iostream>using namespace std;class Base1 {public:Base1() {cout << "Base1 construction" << endl;}~Base1() {cout << "Base1 desstruction" << endl;}
};class Base {public:Base() {cout << "Base construction" << endl;}~Base() {cout << "Base desstruction" << endl;}
private:Base1 b1;
};class Drive1 : public Base {public:Drive1() {cout << "Drive1 construction" << endl;}~Drive1() {cout << "Drive1 desstruction" << endl;}
};class Drive : public Base {public:Drive() {cout << "Drive construction" << endl;}~Drive() {cout << "Drive desstruction" << endl;}
private:Drive1 d1;
};// =======================================
class MDrive1 {public:MDrive1() {cout << "MDrive1 construction" << endl;}~MDrive1() {cout << "MDrive1 desstruction" << endl;}
};class MDrive2 {public:MDrive2() {cout << "MDrive2 construction" << endl;}~MDrive2() {cout << "MDrive2 desstruction" << endl;}
};class MBase1 {public:MBase1() {cout << "MBase1 construction" << endl;}~MBase1() {cout << "MBase1 desstruction" << endl;}
};class MBase2 {public:MBase2() {cout << "MBase2 construction" << endl;}~MBase2() {cout << "MBase2 desstruction" << endl;}
};class MDrive : public MBase1, public MBase2 {public:MDrive() {cout << "MDrive construction" << endl;}~MDrive() {cout << "MDrive desstruction" << endl;}
private:MDrive1 md1;MDrive2 md2;
};int main() {Drive d;cout << "-----------------" << endl;MDrive md;return 0;
}

运行结果:

Base1 construction
Base construction
Base1 construction
Base construction
Drive1 construction
Drive construction
-----------------
MBase1 construction
MBase2 construction
MDrive1 construction
MDrive2 construction
MDrive construction
MDrive desstruction
MDrive2 desstruction
MDrive1 desstruction
MBase2 desstruction
MBase1 desstruction
Drive desstruction
Drive1 desstruction
Base desstruction
Base1 desstruction
Base desstruction
Base1 desstruction

6. 虚函数表和虚函数表指针(vptr)的创建时机

7. 虚析构函数的作用

#include <iostream>
using namespace std;class Base {public:virtual ~Base() {cout << "Base::~Base()" << endl; }
};class Drive : public Base {public:~Drive() {cout << "Drive::~Drive()" << endl;}
};int main() {// Driver d;  //早绑定Base *p = new Drive(); delete p;return 0;
}

8. 智能指针种类以及使用场景

#include <memory>
#include <iostream>
#include <vector>
using namespace std;class B;
class A {public:~A() {cout << "A::~A()" << endl;}weak_ptr<B> spb;
};class B {public:~B() {cout << "B::~B()" << endl;}weak_ptr<A> spb;
};class T : public enable_shared_from_this<T> {public:shared_ptr<T> self() {return shared_from_this();}
};class T1 {};unique_ptr<T1> get_unique() {unique_ptr<T1> up;return up;
}
void func(int *p) {if () {return;}delete p;
}int main() {// 循环引用 shared_ptr<A> sp1 = make_shared<A>();\shared_ptr<B> sp2 = make_shared<B>();sp1->spb = sp2;sp2->spa = sp1;cout << "A.use_counnt():" << sp1.use_count() << " B.use_count():" << sp2.count() << endl;{int *p = new int;delete p;p = nullptr;}{int *p = new int;int *p1 = p;int *p2 = p;int *p3 = p;int *p4 = p;delete p;p = nullptr;// p1.. 操作不存在的资源 }{int *p = new int;func(p);}// 智能指针使用场景vector<shared_ptr<T>> vec;vec.clear();{//不要暴露裸指针 //错误做法 p在后面可能被用到int *p = new int();shared_ptr<int> sp = shared_ptr<int>(p);//正确做法shared_ptr<int> sp = shared_ptr<int>(new int);int *p = sp.get(); //尽量不要使用这个接口 //建议做法shared_ptr<int> sp = make_shared<int>();}return 0;
}

9.C++ 11用过哪些新特性

10.动态库与静态库区别

#include <iostream>#include "api.h"using std::cout;
using std::endl;int main() {cout << "add(1, 2) = " << add(1, 2) << endl;cout << "del(1, 2) = " << del(1, 2) << endl;return 0;
}
#include "api.h"int del(int a, int b) {return a - b;
}
#include "api.h"int add(int a, int b) {return a + b;
}
#pragma onceint add(int a, int b);int del(int a, int b);

生成.o文件:

  1. g++ -c add.cc -o add.o
  2. g++ -c del.cc -o del.o

编译成静态库:

  1. ar rcs libapi.a del.o add.o
  2. g++ main.cc libapi.a -o static_main

编译成动态库:

  1. g++ -shared -fPIC -o libapi.so del.o add.o
  2. g++ main.cc -o dynamic_main -L./ -lapi -I./
  3. export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/workspace/ykhe/practice //动态库运行需要指定路径

11.左值引用与右值引用的区别?右值引用的意义?

参考

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,点击立即学习:https://course.0voice.com/v1/course/intro?courseId=5&agentId=0

C++ 面向对象常见问题相关推荐

  1. python入门基础代码图-【01】Python基础入门 (全)

    一.字符串 1. 字符串切片 切片: name="abcdef" name[2:5]="cde" 跳取: name="abcdef" nam ...

  2. python基础代码大全-【01】Python基础入门 (全)

    一.字符串 1. 字符串切片 切片: name="abcdef" name[2:5]="cde" 跳取: name="abcdef" nam ...

  3. 面向对象编程概念_如何向6岁的孩子解释面向对象的编程概念

    面向对象编程概念 by Alexander Petkov 通过亚历山大·佩特科夫(Alexander Petkov) Have you noticed how the same cliche ques ...

  4. JS中的面向对象编程

    JS中的面向对象编程 小课堂 目录 1.背景介绍 2.知识剖析 3.常见问题 4.解决方案 5.编码实战 6.扩展思考 7.参考文献 8.更多讨论 1.背景介绍 什么是对象? ECMA-262把对象定 ...

  5. 笨办法学python47 原理_41:学会说面向对象

    # 练习41.学会说面向对象 在这个练习中,我要教你如何说"面向对象",我要给你一些你需要知道定义的词.然后我会给你一组你必须了解的句子,最后我会给你一大堆练习,你必须完成这练习题 ...

  6. JAVA基础-面向对象07

    一.代码块 1. 含义: 就是使用大括号括起来的一段代码 格式 { 代码: } 2.静态代码块 格式 static{ 代码: } 书写位置: 直接书写在类中成员位置: 怎么执行呢? 在类加载的最后一步 ...

  7. React.js 开发常见问题

    React.js 开发常见问题 我需要为 React.js 雇用专门的开发人员,还是说只要会 JavaScript 的员工就行? 如果你有了一支熟练的 JavaScript 开发团队,那么使用 Rea ...

  8. Spring/SpingMVC常见问题总结

    Spring/SpingMVC常见问题总结 目录 为什么要使用 spring? 解释一下什么是 aop? 解释一下什么是 ioc? spring 有哪些主要模块? spring 常用的注入方式有哪些? ...

  9. 【面试】Java面试常见问题汇总(不含答案)、面试指导学习笔记

    面试常见问题角度 String是基本数据类型吗? int和Integer有什么区别? HashMap和HashTable的区别,及其实现原理. ArrayList/HashMap的源码.如何实现源码 ...

最新文章

  1. 腾讯开源基于 mmap 的高性能 key-value 组件 MMKV
  2. ACM 会场安排问题
  3. linux安装mysql遇到的问题_Linux下安装MySQL5.7及遇到的问题解决方法
  4. 四级口语计算机对话,四级英语口语对话常用的句子
  5. 使用UIWebView中html标签显示富文本
  6. Hibernate查询技术(2)
  7. swift可选类型_Swift可选
  8. PHP删除字符串最后一个字符的几种方法总结
  9. NOIp2017 题解
  10. 提高效率:17款超赞的谷歌chrome浏览器插件、扩展程序
  11. RadAsm:object file not found
  12. matlab 批量取消注释,MATLAB中多行注释以及取消的快捷键
  13. JavaScript基础教程之flag的用法
  14. maven [INFO] No proxies configured [INFO] No proxy was configured, downloading directly
  15. 数学建模模型_浅谈对数学建模,数据挖掘,数据分析和数据模型的区别
  16. 2020大疆数字IC校招笔试题(3)——CMOS 反相器【CMOS逻辑】【MOS管】【PMOS】【NMOS】
  17. 1-5 第一个C语言程序
  18. ue4 培养罐液体效果
  19. uniapp uview 1.x设置遮罩层全屏loading
  20. GEE:批量下载数据,按月合成,不同景,全实验区域,一键执行

热门文章

  1. win虚拟机基础配置(win2003server winxp)及磁盘文件隐藏
  2. 10个最好的免费读书网站
  3. 【算法分析】ABCDE*A=EEEEEE的问题
  4. 移动端问题列表及解决方案(转)
  5. 听完“硅谷来信”的感受
  6. [转] 美团点评酒旅前端的技术体系
  7. 怎样让HTML自动开始时间,【jQuery日期处理】选择开始时间,自动结束时间
  8. CentOS7安装iftop
  9. js的if判断,关于==的判断
  10. HTTPS端口443被程序vmware-hostd.exe占用的解决