C++ 基类中静态成员初始化问题、基类头文件中定义类外变量重定义问题的解决过程

今天需要在基类中定义一个静态list以供所有继承此基类的成员使用,去掉无关函数,简单示例如下

//基类头文件
#pragma once
#include <list>
class base
{
public:
 static std::list<void*> deleteptr;
};
//继承类A头文件
#pragma once
#include "base.h"
class inherit_class_A :
	public base
{
public:
	void use_list();
};
//继承类A源文件
#include "stdafx.h"
#include "inherit_class_A.h"
void inherit_class_A::use_list()
{
	char* ptr = new char;
	deleteptr.push_back(ptr);
}

发现会在编译阶段错误
错误 1 error LNK2001: 无法解析的外部符号 “public: static class std::list<void *,class std::allocator<void *> > base::deleteptr” (?deleteptr@base@@2V? l i s t @ P A X V ? list@PAXV? list@PAXV?allocator@PAX@std@@@std@@A) H:\codestudy\19.08_code\class_static\class_static\inherit_class_A.obj class_static
初步定位原因是因为deleteptr.push_back(ptr);调用了 static std::list<void*> deleteptr;
而其没有进行初始化。

基类中静态成员初始化问题

  • 尝试1:将其初始化,查阅资料后发现类中的static变量只有const static能够在定义的时候进行初始化,而我需要使用这个变量,不能为const。此方法不行
  • 尝试2:在成员函数中进行初始化,如deleteptr = std::list<void*>();,依然会报之前的编译错误。此方法不行
    后来查阅资料我发现若要初始化类内static list,需要在类外使用std::list<void*> base::deleteptr;进行类外初始化。
    注意: 如果包含静态成员变量的基类被多个类继承,将不能在基类的头文件外进行类外初始化,因为这样会导致重定义问题,需要在不会引起重定义问题的地方进行初始化。

基类头文件中定义类外变量重定义问题

  • 最终方案:将 static std::list<void*> deleteptr;放在头文件中其他位置,解决问题,如下
//基类头文件
#pragma once
#include <list>
static std::list<void*> deleteptr;
class base
{
public:
};

因为有两个基类引用了这个.h文件,会引起重定义的问题。
关于为什么添加了#pragma once还是会引起重定义的问题? 我的想应该是这样的
#pragma once和#ifndef都是防止一个文件被重复包含,比如C包含B,B包含A,添加这句代码就能防止C将B包含过的A再包含一次,不然的话C里面会定义两次A里面的东西。但是如果两个继承类都分别包含基类的头文件,那么他们都分别包含了一次头文件,并没有多次进行包含,但是基类类外已经有多个 static std::list<void*> deleteptr;
被继承类包含,导致多个deleteptr全局变量,最终导致重定义

为什么这样能解决问题?

静态全局变量有以下特点:
(1)静态变量都在全局数据区分配内存,包括后面将要提到的静态局部变量;
(2)未经初始化的静态全局变量会被程序自动初始化为0(在函数体内声明的自动变量的值是随机的,除非它被显式初始化,而在函数体外被声明的自动变量也会被初始化为0);
(3)静态全局变量在声明它的整个文件都是可见的,而在文件之外是不可见的。
优点:静态全局变量不能被其它文件所用;其它文件中可以定义相同名字的变量,不会发生冲突。
(4)全局变量和全局静态变量的区别
1)全局变量是不显式用static修饰的全局变量,全局变量默认是有外部链接性的,作用域是整个工程,在一个文件内定义的全局变量,在另一个文件中,通过extern 全局变量名的声明,就可以使用全局变量。
2)全局静态变量是显式用static修饰的全局变量,作用域是声明此变量所在的文件,其他的文件即使用extern声明也不能使用。
引用自这里

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《深入浅出MFC》2/e 简体版 目录 第0章 你一定要知道(导读) 这本书适合谁 你需要什么技术基础 你需要什么软硬件环境 让我们使用同一种语言 本书符号习惯 本书例程的取得 范例程序说明 与前版本之差异 如何联络作者 第一篇 勿在浮砂筑高台 第1章 Win32程序基本概念 Win32程序开发流程 需要什么函数库(.LIB) 需要什么头文件(.H) 以消息为基础,以事件驱动之(message based,event driven) 一个具体而微的Win32程序 程序进入点WinMain 窗口类之注册与窗口之诞生 消息循环 窗口的生命枢:窗口函数 消息映射(Message Map)的雏形 对话框的运行 模块定义文件(.DEF) 资源描述档(.RC) Widnows程序的生与死 空闲时间的处理:OnIdle Console程序 Console程序与DOS程序的差别 Console程序的编译链接 JBACKUP:Win32 Console程序设计 MFCCON:MFC Console程序设计 行程与线程(Process and Thread) 核心对象 一个行程的诞生与死亡 产生子行程 一个线程的诞生与死亡 以_beginthreadex取代CreateThread 线程优先级(Priority) 多线程程序设计实例 第2章 C++要性质 类及其成员——谈封装(encapsulation) 基类与派生类:谈继承(Inheritance) this指针 虚拟函数与多态(Polymorphism) 类与对象大解剖 Object slicing与虚拟函数 静态成员变量与函数) C++程序的生与死:兼谈构造函数与解构函数 四种不同的对象生存方式(in stack、in heap、global、local static) 执行期类型信息(RTTI) 动态生成(Dynamic Creation) 异常处理(Exception Handling) Template Template Functions Template Classes Template的编译与链接 第3章 MFC六大关键技术之仿真 MFC类层次结构 Frame 1范例程序 MFC程序的初始化过程 Frame 2范例程序 RTTI(执行期类型识别) 类别型录网与CRuntimeClass DECLARE_DYNAMIC/IMPLEMENT_DYNAMIC宏 Frame 3范例程序 IsKindOf(类型识别) Frame 4范例程序 Dynamic Creation(动态生成) DECLARE_DYNCREATE/IMPLEMENT_DYNCREATE宏 Frame 6范例程序 Persistence(永久保存)机制 Serialize(数据读写) …… 第二篇 欲善工事先利其器 第4章 Visual C++集成开发环境 第三篇 浅出MFC程序设计 第5章 总观Application Framework 第6章 MFC程序的生死因果 第7章 简单而完整:MFC骨干程序 第四篇 深入MFC程序设计 第8章 Document-View深入探讨 第9章 消息映射与命令传递 第10章 MFC与对话盒 第11章 View功能的加强与绘效率的提高 第12章 打印与预览 第13章 多文件与多显示 第14章 MFC多线程程序设计 第15章 定制一个AppWizard 第16章 站上众人的肩膀——使用Components&activeX; Controls
C++ Primer文版(第5版)[203M]分3个压缩包 本书是久负盛名的C++经典教程,其内容是C++大师Stanley B. Lippman丰富的实践经验和C++标准委员会原负责人Josée Lajoie对C++标准深入理解的完美结合,已经帮助全球无数程序员学会了C++。 对C++基本概念和技术全面而且权威的阐述,对现代C++编程风格的强调,使本书成为C++初学者的最佳指南;对于高级程序员,本书也是不可或缺的参考书。 目录 第1章 开始 1   1.1 编写一个简单的C++程序 2   1.1.1 编译、运行程序 3   1.2 初识输入输出 5   1.3 注释简介 8   1.4 控制流 10   1.4.1 while语句 10   1.4.2 for语句 11   1.4.3 读取数量不定的输入数据 13   1.4.4 if语句 15   1.5 类简介 17   1.5.1 Sales_item类 17   1.5.2 初识成员函数 20   1.6 书店程序 21   小结 23   术语表 23   第Ⅰ部分 C++基础 27   第2章 变量和基本类型 29   2.1 基本内置类型 30   2.1.1 算术类型 30   2.1.2 类型转换 32   2.1.3 字面值常量 35   2.2 变量 38   2.2.1 变量定义 38   2.2.2 变量声明和定义的关系 41   2.2.3 标识符 42   2.2.4 名字的作用域 43   2.3 复合类型 45   2.3.1 引用 45   2.3.2 指针 47   2.3.3 理解复合类型的声明 51   2.4 const限定符 53   2.4.1 const的引用 54   2.4.2 指针和const 56   2.4.3 顶层const 57   2.4.4 constexpr和常量表达式 58   2.5 处理类型 60   2.5.1 类型别名 60   2.5.2 auto类型说明符 61   2.5.3 decltype类型指示符 62   2.6 自定义数据结构 64   2.6.1 定义Sales_data类型 64   2.6.2 使用Sales_data类 66   2.6.3 编写自己的头文件 67   小结 69   术语表 69   第3章 字符串、向量和数组 73   3.1 命名空间的using声明 74   3.2 标准库类型string 75   3.2.1 定义初始化string对象 76   3.2.2 string对象上的操作 77   3.2.3 处理string对象的字符 81   3.3 标准库类型vector 86   3.3.1 定义初始化vector对象 87   3.3.2 向vector对象添加元素 90   3.3.3 其他vector操作 91   3.4 迭代器介绍 95   3.4.1 使用迭代器 95   3.4.2 迭代器运算 99   3.5 数组 101   3.5.1 定义初始化内置数组 101   3.5.2 访问数组元素 103   3.5.3 指针和数组 105   3.5.4 C风格字符串 109   3.5.5 与旧代码的接口 111   3.6 多维数组 112   小结 117   术语表 117   第4章 表达式 119   4.1 基础 120   4.1.1 基本概念 120   4.1.2 优先级与结合律 121   4.1.3 求值顺序 123   4.2 算术运算符 124   4.3 逻辑和关系运算符 126   4.4 赋值运算符 129   4.5 递增和递减运算符 131   4.6 成员访问运算符 133   4.7 条件运算符 134   4.8 位运算符 135   4.9 sizeof运算符 139   4.10 逗号运算符 140   4.11 类型转换 141   4.11.1 算术转换 142   4.11.2 其他隐式类型转换 143   4.11.3 显式转换 144   4.12 运算符优先级表 147   小结 149   术语表 149   第5章 语句 153   5.1 简单语句 154   5.2 语句作用域 155   5.3 条件语句 156   5.3.1 if语句 156   5.3.2 switch语句 159   5.4 迭代语句 165   5.4.1 while语句 165   5.4.2 传统的for语句 166   5.4.3 范围for语句 168   5.4.4 do while语句 169   5.5 跳转语句 170   5.5.1 break语句 170   5.5.2 continue语句 171   5.5.3 goto语句 172   5.6 TRY语句块和异常处理 172   5.6.1 throw表达式 173   5.6.2 try语句块 174   5.6.3 标准异常 176   小结 178   术语表 178   第6章 函数 181   6.1 函数基础 182   6.1.1 局部对象 184   6.1.2 函数声明 186   6.1.3 分离式编译 186   6.2 参数传递 187   6.2.1 传值参数 187   6.2.2 传引用参数 188   6.2.3 const形参和实参 190   6.2.4 数组形参 193   6.2.5 main:处理命令行选项 196   6.2.6 含有可变形参的函数 197   6.3 返回类型和return语句 199   6.3.1 无返回值函数 200   6.3.2 有返回值函数 200   6.3.3 返回数组指针 205   6.4 函数载 206   6.4.1 载与作用域 210   6.5 特殊用途语言特性 211   6.5.1 默认实参 211   6.5.2 内联函数和constexpr函数 213   6.5.3 调试帮助 215   6.6 函数匹配 217   6.6.1 实参类型转换 219   6.7 函数指针 221   小结 225   术语表 225   第7章 类 227   7.1 定义抽象数据类型 228   7.1.1 设计Sales_data类 228   7.1.2 定义改进的Sales_data类 230   7.1.3 定义类相关的非成员函数 234   7.1.4 构造函数 235   7.1.5 拷贝、赋值和析构 239   7.2 访问控制与封装 240   7.2.1 友元 241   7.3 类的其他特性 243   7.3.1 类成员再探 243   7.3.2 返回*this的成员函数 246   7.3.3 类类型 249   7.3.4 友元再探 250   7.4 类的作用域 253   7.4.1 名字查找与类的作用域 254   7.5 构造函数再探 257   7.5.1 构造函数初始值列表 258   7.5.2 委托构造函数 261   7.5.3 默认构造函数的作用 262   7.5.4 隐式的类类型转换 263   7.5.5 聚合类 266   7.5.6 字面值常量类 267   7.6 类的静态成员 268   小结 273   术语表 273   第Ⅱ部 C++标准库 275   第8章 IO库 277   8.1 IO类 278   8.1.1 IO对象无拷贝或赋值 279   8.1.2 条件状态 279   8.1.3 管理输出缓冲 281   8.2 文件输入输出 283   8.2.1 使用文件流对象 284   8.2.2 文件模式 286   8.3 string流 287   8.3.1 使用istringstream 287   8.3.2 使用ostringstream 289   小结 290   术语表 290   第9章 顺序容器 291   9.1 顺序容器概述 292   9.2 容器库概览 294   9.2.1 迭代器 296   9.2.2 容器类型成员 297   9.2.3 begin和end成员 298   9.2.4 容器定义初始化 299   9.2.5 赋值和swap 302   9.2.6 容器大小操作 304   9.2.7 关系运算符 304   9.3 顺序容器操作 305   9.3.1 向顺序容器添加元素 305   9.3.2 访问元素 309   9.3.3 删除元素 311   9.3.4 特殊的forward_list操作 312   9.3.5 改变容器大小 314   9.3.6 容器操作可能使迭代器失效 315   9.4 vector对象是如何增长的 317   9.5 额外的string操作 320   9.5.1 构造string的其他方法 321   9.5.2 改变string的其他方法 322   9.5.3 string搜索操作 325   9.5.4 compare函数 327   9.5.5 数值转换 327   9.6 容器适配器 329   小结 332   术语表 332   第10章 泛型算法 335   10.1 概述 336   10.2 初识泛型算法 338   10.2.1 只读算法 338   10.2.2 写容器元素的算法 339   10.2.3 排容器元素的算法 342   10.3 定制操作 344   10.3.1 向算法传递函数 344   10.3.2 lambda表达式 345   10.3.3 lambda捕获和返回 349   10.3.4 参数绑定 354   10.4 再探迭代器 357   10.4.1 插入迭代器 358   10.4.2 iostream迭代器 359   10.4.3 反向迭代器 363   10.5 泛型算法结构 365   10.5.1 5类迭代器 365   10.5.2 算法形参模式 367   10.5.3 算法命名规范 368   10.6 特定容器算法 369   小结 371   术语表 371   第11章 关联容器 373   11.1 使用关联容器 374   11.2 关联容器概述 376   11.2.1 定义关联容器 376   11.2.2 关键字类型的要求 378   11.2.3 pair类型 379   11.3 关联容器操作 381   11.3.1 关联容器迭代器 382   11.3.2 添加元素 383   11.3.3 删除元素 386   11.3.4 map的下标操作 387   11.3.5 访问元素 388   11.3.6 一个单词转换的map 391   11.4 无序容器 394   小结 397   术语表 397   第12章 动态内存 399   12.1 动态内存与智能指针 400   12.1.1 shared_ptr类 400   12.1.2 直接管理内存 407   12.1.3 shared_ptr和new结合使用 412   12.1.4 智能指针和异常 415   12.1.5 unique_ptr 417   12.1.6 weak_ptr 420   12.2 动态数组 423   12.2.1 new和数组 423   12.2.2 allocator类 427   12.3 使用标准库:文本查询程序 430   12.3.1 文本查询程序设计 430   12.3.2 文本查询程序类的定义 432   小结 436   术语表 436   第Ⅲ部分 类设计者的工具 437   第13章 拷贝控制 439   13.1 拷贝、赋值与销毁 440   13.1.1 拷贝构造函数 440   13.1.2 拷贝赋值运算符 443   13.1.3 析构函数 444   13.1.4 三/五法则 447   13.1.5 使用=default 449   13.1.6 阻止拷贝 449   13.2 拷贝控制和资源管理 452   13.2.1 行为像值的类 453   13.2.2 定义行为像指针的类 455   13.3 交换操作 457   13.4 拷贝控制示例 460   13.5 动态内存管理类 464   13.6 对象移动 470   13.6.1 右值引用 471   13.6.2 移动构造函数和移动赋值运算符 473   13.6.3 右值引用和成员函数 481   小结 486   术语表 486   第14章 操作载与类型转换 489   14.1 基本概念 490   14.2 输入和输出运算符 494   14.2.1 载输出运算符<> 495   14.3 算术和关系运算符 497   14.3.1 相等运算符 497   14.3.2 关系运算符 498   14.4 赋值运算符 499   14.5 下标运算符 501   14.6 递增和递减运算符 502   14.7 成员访问运算符 504   14.8 函数调用运算符 506   14.8.1 lambda是函数对象 507   14.8.2 标准库定义的函数对象 509   14.8.3 可调用对象与function 511   14.9 载、类型转换与运算符 514   14.9.1 类型转换运算符 514   14.9.2 避免有二义性的类型转换 517   14.9.3 函数匹配与载运算符 521   小结 523   术语表 523   第15章 面向对象程序设计 525   15.1 OOP:概述 526   15.2 定义基类和派生类 527   15.2.1 定义基类 528   15.2.2 定义派生类 529   15.2.3 类型转换与继承 534   15.3 虚函数 536   15.4 抽象基类 540   15.5 访问控制与继承 542   15.6 继承的类作用域 547   15.7 构造函数与拷贝控制 551   15.7.1 虚析构函数 552   15.7.2 合成拷贝控制与继承 552   15.7.3 派生类的拷贝控制成员 554   15.7.4 继承的构造函数 557   15.8 容器与继承 558   15.8.1 编写Basket类 559   15.9 文本查询程序再探 562   15.9.1 面向对象的解决方案 563   15.9.2 Query_base类和Query类 567   15.9.3 派生类 568   15.9.4 eval函数 571   小结 575   术语表 575   第16章 模板与泛型编程 577   16.1 定义模板 578   16.1.1 函数模板 578   16.1.2 类模板 583   16.1.3 模板参数 592   16.1.4 成员模板 595   16.1.5 控制实例化 597   16.1.6 效率与灵活性 599   16.2 模板实参推断 600   16.2.1 类型转换与模板类型参数 601   16.2.2 函数模板显式实参 603   16.2.3 尾置返回类型与类型转换 604   16.2.4 函数指针和实参推断 607   16.2.5 模板实参推断和引用 608   16.2.6 理解std::move 610   16.2.7 转发 612   16.3 载与模板 614   16.4 可变参数模板 618   16.4.1 编写可变参数函数模板 620   16.4.2 包扩展 621   16.4.3 转发参数包 622   16.5 模板特例化 624   小结 630   术语表 630   第Ⅳ部分 高级主题 633   第17章 标准库特殊设施 635   17.1 tuple类型 636   17.1.1 定义初始化tuple 637   17.1.2 使用tuple返回多个值 638   17.2 BITSET类型 640   17.2.1 定义初始化bitset 641   17.2.2 bitset操作 643   17.3 正则表达式 645   17.3.1 使用正则表达式库 646   17.3.2 匹配与Regex迭代器类型 650   17.3.3 使用子表达式 653   17.3.4 使用regex_replace 657   17.4 随机数 659   17.4.2 其他随机数分布 663   bernoulli_distribution类 665   17.5 IO库再探 666   17.5.1 格式化输入与输出 666   17.5.2 未格式化的输入/输出操作 673   17.5.3 流随机访问 676   小结 680   术语表 680   第18章 用于大型程序的工具 683   18.1 异常处理 684   18.1.1 抛出异常 684   18.1.2 捕获异常 687   18.1.3 函数try语句块与构造函数 689   18.1.4 noexcept异常说明 690   18.1.5 异常类层次 693   18.2 命名空间 695   18.2.1 命名空间定义 695   18.2.2 使用命名空间成员 701   18.2.3 类、命名空间与作用域 705   18.2.4 载与命名空间 708   18.3 多继承与虚继承 710   18.3.1 多继承 711   18.3.2 类型转换与多个基类 713   18.3.3 多继承下的类作用域 715   18.3.4 虚继承 717   18.3.5 构造函数与虚继承 720   小结 722   术语表 722   第19章 特殊工具与技术 725   19.1 控制内存分配 726   19.1.1 载new和delete 726   19.1.2 定位new表达式 729   19.2 运行时类型识别 730   19.2.1 dynamic_cast运算符 730   19.2.2 typeid运算符 732   19.2.3 使用RTTI 733   19.2.4 type_info类 735   19.3 枚举类型 736   19.4 类成员指针 739   19.4.1 数据成员指针 740   19.4.2 成员函数指针 741   19.4.3 将成员函数用作可调用对象 744   19.5 嵌套类 746   19.6 union:一种节省空间的类 749   19.7 局部类 754   19.8 固有的不可移植的特性 755   19.8.1 位域 756   19.8.2 volatile限定符 757   19.8.3 链接指示:extern "C" 758   小结 762   术语表 762   附录A 标准库 765   A.1 标准库名字和头文件 766   A.2 算法概览 770   A.2.1 查找对象的算法 771   A.2.2 其他只读算法 772   A.2.3 二分搜索算法 772   A.2.4 写容器元素的算法 773   A.2.5 划分与排序算法 775   A.2.6 通用排操作 776   A.2.7 排列算法 778   A.2.8 有序序列的集合算法 778   A.2.9 最小值和最大值 779   A.2.10 数值算法 780   A.3 随机数 781   A.3.1 随机数分布 781   A.3.2 随机数引擎 783   C++11的新特性   2.1.1 long long类型 31   2.2.1 列表初始化 39   2.3.2 nullptr常量 48   2.4.4 constexpr变量 59   2.5.1 类型别名声明 60   2.5.2 auto类型指示符 61   2.5.3 decltype类型指示符 62   2.6.1 类内初始化 65   3.2.2 使用auto或decltype缩写类型 79   3.2.3 范围for语句 82   3.3 定义vector对象的vector(向量的向量) 87   3.3.1 vector对象的列表初始化 88   3.4.1 容器的cbegin和cend函数 98   3.5.3 标准库begin和end函数 106   3.6 使用auto和decltype简化声明 115   4.2 除法的舍入规则 125   4.4 用大括号包围的值列表赋值 129   4.9 将sizeof用于类成员 139   5.4.3 范围for语句 168   6.2.6 标准库initializer_list类 197   6.3.2 列表初始化返回值 203   6.3.3 定义尾置返回类型 206   6.3.3 使用decltype简化返回类型定义   6.5.2 constexpr函数 214   7.1.4 使用=default生成默认构造函数 237   7.3.1 类对象成员的类内初始化 246   7.5.2 委托构造函数 261   7.5.6 constexpr构造函数 268   8.2.1 用string对象处理文件名 284   9.1 array和forward_list容器 293   9.2.3 容器的cbegin和cend函数 298   9.2.4 容器的列表初始化 300   9.2.5 容器的非成员函数swap 303   9.3.1 容器insert成员的返回类型 308   9.3.1 容器的emplace成员的返回类型 308   9.4 shrink_to_fit 318   9.5.5 string的数值转换函数 327   10.3.2 Lambda表达式 346   10.3.3 Lambda表达式的尾置返回类型 353   10.3.4 标准库bind函数 354   11.2.1 关联容器的列表初始化 377   11.2.3 列表初始化pair的返回类型 380   11.3.2 pair的列表初始化 384   11.4 无序容器 394   12.1 智能指针 400   12.1.1 shared_ptr类   12.1.2 动态分配对象的列表初始化 407   12.1.2 auto和动态分配 408   12.1.5 unique_ptr类 417   12.1.6 weak_ptr类 420   12.2.1 范围for语句不能应用于动态分配数组 424   12.2.1 动态分配数组的列表初始化 424   12.2.1 auto不能用于分配数组 424   12.2.2 allocator::construct可使用任意构造函数 428   13.1.5 将=default用于拷贝控制成员 449   13.1.6 使用=default阻止拷贝类对象 449   13.5 用移动类对象代替拷贝类对象 469   13.6.1 右值引用 471   13.6.1 标准库move函数 472   13.6.2 移动构造函数和移动赋值 473   13.6.2 移动构造函数通常应该是noexcept 473   13.6.2 移动迭代器 480   13.6.3 引用限定成员函数 483   14.8.3 function类模板 512   14.9.1 explicit类型转换运算符 516   15.2.2 虚函数的override指示符 530   15.2.2 通过定义类为final来阻止继承 533   15.3 虚函数的override和final指示符 538   15.7.2 删除的拷贝控制和继承 553   15.7.4 继承的构造函数 557   16.1.2 声明模板类型形参为友元 590   16.1.2 模板类型别名 590   16.1.3 模板函数的默认模板参数 594   16.1.5 实例化的显式控制 597   16.2.3 模板函数与尾置返回类型 605   16.2.5 引用折叠规则 609   16.2.6 用static_cast将左值转换为右值 612   16.2.7 标准库forward函数 614   16.4 可变参数模板 618   16.4 sizeof...运算符 619   16.4.3 可变参数模板与转发 622   17.1 标准库Tuple类模板 636   17.2.2 新的bitset运算 643   17.3 正则表达式库 645   17.4 随机数库 659   17.5.1 浮点数格式控制 670   18.1.4 noexcept异常指示符 690   18.1.4 noexcept运算符 691   18.2.1 内联名字空间 699   18.3.1 继承的构造函数和多继承 712   19.3 有作用域的enum 736   19.3 说明类型用于保存enum对象 738   19.3 enum的提前声明 738   19.4.3 标准库mem_fn类模板 746   19.6 类类型的联合成员 75
目录 第1篇初级篇 第1章 初识C++ 1.1 c++简介 1.2 C++与C的区别 1.3 学习c++之前需要先学C吗 1.4 c++与其他语言的区别 1.5 c++的版本以及安装问题 第2章 做一个最简短的C4-+程序 2.1 简单的屏幕输出小程序 2.2 输出语句的使用 2.3 std::介绍 2.4 iostream与iostream.h的区别 2.5 问题 2.6 注释 2.7 总结 第3章 初步了解函数 3.1 一个简单的函数 3.2 函数的传参 3.3 函数的返回值、参数与变量 3.4.函数的声明与定义 3.5 局部变量 3.6 全局变量 3.7 总结 第4章 C4-+数据类型 4.1 变量定义 4.2 将变量及数据存储在内存 4.3 布尔型变量 4.4 字符型变量 4.5 wchart双字符型变量 4.6 整型概述 4.7 整型变量定义 4.8 浮点型变量 4.9 常量 4.10枚举型常量 第5章 if语句与运算符 5.1 语句的定义 5.2 块的定义 5.3 表达式的定义 5.4 运算符的定义 5.4.1 赋值运算符的定义 5.4.2 数学运算符的定义 5.4.3 赋值运算符与数学运算符的联合 5.5 自加与自减 5.5.1 前置 5.5.2 后置 5.6 表达式的优先级 5.7 关系运算符 5.8 if语句 5.8.1 else语句 5.8.2 elseif语句 5.8.3 if语句的嵌套 5.9 逻辑运算符及其使用 5.9.1 逻辑“与” 5.9.2 逻辑“或” 5.9.3 逻辑“非” 5.9.4 逻辑运算符的优先级 5.9.5 运算式的真假关系 5.1 0三目运算符 5.1 0.1 三目运算符的优先问题 5.1 0.2 三目运算符的使用问题 5.1 0.3 三目运算符的型别问题 5.1 0.4 三目运算符在字符型变量的应用 5.1 1复杂嵌套的if语句 5.1 2总结 第6章 面向对象 6.1 面向对象程序语言的主要特征 6.2 类、对象和成员 6.3 类、对象和成员的使用方法及区别 6.3.1 声明一个类 6.3.2 命名习惯 6.3.3 定义一个对象 6.3.4 类与对象的区别 6.3.5 对象与成员的关系 6.3.6 不要给类赋值 6.3.7 对象只能调用类存在的方法 6.4 公有 6.5 私有 6.6 成员函数的声明和定义 6.7 内联函数 6.7.1 普通内联函数 6.7.2 内联成员函数 6.8 头文件与源文件 6.9 const成员函数 6.10构造函数 6.11默认构造函数 6.12析构函数 6.13析构对象数组 6.14总结 第7章 循环语句 7.1 循环语句的前身——goto语句 7.2 慎用goto语句 7.3 while语句 7.3.1 带运算符的while语句 7.3.2 以字符为条件的while语句 7.3.3 限定while循环的次数 7.3.4 continue语句 7.3.5 break语句 7.3.6 永不休止的while循环 7.4. do……while循环 7.5 for循环 7.5.1 灵活的for循环 7.5.2 条件为空的for循环 7.5.3 执行为空的for循环 7.5.4 嵌套的for循环 7.6 switch语句 7.6.1 switch语句常见错误 7.6.2 switch的菜单功能 7.7 总结 第8章 指针 8.1 什么是地址 8.2 用指针来保存地址 8.2.1 空指针 8.2.2 指针与变量类型 8.2.3 用指针来访问值 8.2.4 指针地址、指针保存的地址和 该地址的值 8.2.5 指针对数值的操作 8.2.6 更换指针保存的地址 8.3 为什么使用指针 8.3.1 栈和堆 8.3.2 用指针创建堆空间 8.3.3 用指针删除堆空间 8.4 动态内存 8.4.1 内存泄漏 8.4.2 在堆创建对象 8.4.3 在堆删除对象 8.4.4 访问堆的数据成员 8.4..5 在构造函数开辟内存空间 8.4.6 对象在栈与堆的不同 8.5 this指针 8.6 指针的常见错误 8.7 指针运算 8.7.1 指针的加减运算 8.7.2 指针的赋值运算 8.7 _3指针的相减运算 8.7.4 指针的比较运算 8.8 指针 8.8.1 常量指针 8.8.2 指向常量的指针 8.8.3 指向常量的常指针 8.9 总结 第9章 引用 9.1 什么是引用 9.1.1 引用的地址 9.1.2 引用就是别名常量 9.1.3 引用对象 9.1 4空引用 9.2 函数的参数传递 9.2.1 按值传递 9.2.2 按址传递 9.2.3 按别名传递 9.2.4 让函数返回多个值 9.3 传递对象 9.3.1 按值来传递对象 9.3.2 利用指针来传递对象 9.3.3 利用cost指针来传递对象 9.3.4 利用引用来传递对象 9.3.5 到底是使用引用还是指针 9.3.6 引用和指针可以一块用 9.4 引用应注意的问题 9.4.1 引用容易犯的错误 9.4.2 引用一个按值返回的堆对象 9.4 -3引用一个按别名返回的堆对象 9.4.4 在哪里创建,就在哪里释放 9.5 总结 第10章 深入函数 10.1 函数载 10.1.1 普通函数的载 10.1.2 成员函数的载 10.2 函数的默认参数 10.3 载构造函数 10.3.1 成员变量的赋值与初始化 10.3.2 成员变量初始化与构造函数 10.3.3 复制构造函数 10.3.4 构造函数和new运算符 10.3.5 再谈默认构造函数 10.4.析构函数和delete运算符 10.4..1 默认析构函数 10.4.2 调用构造函数进行类型转换 10.5 浅层复制构造函数 10.6 深层复制构造函数 第11章 运算符载 11.1 运算符载 11.2 在成员函数实现自加 11.3 载前置自加运算符 11.4 创建临时对象 11.5 创建无名临时对象 11.6 取消创建临时对象 11.7 载后置自加运算符 11.8 载加法运算符函数operator+ 11.9 载赋值运算符函数operator 11.10转换类型运算符 11.10.1 温习调用构造函数实现的类型转换 11.10.2 通过构造函数将变量转换为一个对象的成员变量 11.10.3 通过operator关键字进行转换 11.11什么可以载,什么不可以载 第12章 继承 12.1 什么是继承和派生 12.1.1 复杂的继承和派生 12.1.2 继承和派生如何在C++实现 12.1.3 继承的种类及语法 12.1.4 单一继承 12.2 公有型、保护型和私有型 12.3 访问权限 12.4 多继承 12.5 继承的构造与析构 12.6 合理利用基类构造函数 12.7 继承和载的两义性问题 12.7.1 多继承容易产生两义性 12.7.2 继承载 12.7.3 两义性的归属问题 12.7.4 减少两义性产生的混淆问题 12.7.5 虚基类不会产生两义性 12.8 总结 第13章 虚函数 13.1 指向子对象的父指针 13.2 虚函数 13.3 拳击游戏 13.4 继承是否可以实现多态性 13.5 在编译时的静态联编 13.6 在运行时的静态联编 13.7 在运行时的动态联编 13.8 在编译时的动态联编 13.9 调用虚函数 13.9.1 在虚函数调用成员函数 13.9.2 3种调用虚函数的方式比较 13.10被继承的虚函数仍然是虚函数 13.11系统是如何调用虚函数的 13.12在虚函数使用成员名限定 13.13虚析构函数 13.14总结 第14章 数组 14.1 数组的基本用法 14.1.1 什么是数组 14.1.2数组元素 14.1.3数组下标越界 14.1.4 倒序输出 14.1.5 将数组的下标定义为常量 14.1.6 手动操作数组元素 14.1.7 数组的初始化 14.2 数组的用途 14.2.1 求平均考试成绩 14.2.2 兔子繁殖问题 14.2.3 数字排序问题 14.3 数组在内存的分布 14.4.输出数组名 14.5 数组名与函数 14.6 传递与接收 14.7 数组与函数 14.7.1 函数传参实例一——求数组所有元素的和 14.7.2 函数传参实例二——用递增法查找数据 14.7.3 函数传参实例三——用二分算法查找数据 14.7.4 函数传参实例四——判断数组是否按照顺序排列 14.7.5 函数传参实例五——判断数组排列方式后执行不同的函数 14.8 数组在对象的传参 14.9 对象数组 14.10 在对象数组初始化成员变量 14.11 指针数组 14.12 枚举常量与数组 14.13 多维数组 14.14 多维数组的初始化 14.15 字符数组 14.16 载数组下标操作符 14.17 总结 第15章 链表 15.1 声明链表结构 15.2 简单的图书链表 15.2.1 图书链表 15.2.2 类的链表 15.3 动态链表 15.3.1 动态链表的建立 15.3.2 解决输入字符造成死循环的问题 15.3.3 动态链表的显示 15.3.4 动态链表的删除 第16章 多态性 第17章 类的特殊成员 第2篇 高级篇 第19章 代码用 第20篇 高级篇 第20章 友元类与嵌套类 第21章 流 第22章 命名空间 第23章 模板 第24章 异常和错误处理 第25章 补充知识 附录A ASCII码对照表 附录B C++的关键字 附录C C++常用头文件列表 附录D 运算符的优先级 后记
自己整理的C++要背的一些概念,华南师范大学考c++的建议看看,21届考研有考到哦!!(可打印版) 1. 面向对象的三个基本特征 4 2. 抽象 4 3. 如何实现多态性 4 4. const与define的区别 4 5. static作用 4 6. 静态数据成员与静态成员函数 5 7. 静态数据成员与全局变量的不同 5 8. 为什么引入友元的概念? 5 9. 什么是友元函数? 5 10. 友元成员函数 5 11. 友元类 5 12. 函数载 5 13. 运算符载 6 14. 运算符载函数的使用 6 15. 载运算符的规则 6 16. 为什么要使用继承 6 17. 保护成员的作用 6 18. 多继承 6 19. 虚基类及其作用 6 20. 派生类的构造函数和析构函数的构造规则 7 21. 虚函数及其作用 7 22. 静态关联和动态关联 7 23. 函数载与虚函数的不同 7 24. 虚析构函数 8 25. 纯虚函数 8 26. 抽象类 8 27. 抽象类与接口的区别 8 28. 32.输入输出流 8 29. 标准的输出流对象有哪些 8 30. 标准的输入流对象有哪些 9 31. 文件流类与文件流对象 9 32. 两个短整型数相加后,结果是什么类型? 9 33. 什么是值传递? 9 34. 值传递、引用传递和指针传递的区别是什么? 9 35. 什么是函数模板?什么是模板函数?函数模板有什么用途? 9 36. C++是如何实现函数载的? 10 37. 全局变量和局部变量的主要区别是什么? 使用全局变量有什么好处?有什么坏处? 10 38. 变量定义变量声明有什么区别? 10 39. 引入结构体有什么好处? 10 40. 单链表为什么要引入头结点? 10 41. 结构体类型定义的作用是什么? 结构体类型的变量定义的作用是什么? 10 42. 用自己的话描述逐步细化的过程 10 43. 为什么库的实现文件要包含自己的头文件? 11 44. 什么头文件要包含 #ifndef...#endif这对编译预处理指令? 11 45. 为什么要使用库? 11 46. 用struct定义类型与用class定义类型有什么区别? 11 47. 构造函数和析构函数的作用是什么?它们各有什么特征? 11 48. 友元的作用是什么? 11 49. 静态数据成员有什么特征?有什么用途? 11 50. 在定义一个类时,哪些部分应放在头文件(.h文件),哪些部分应放在实现文件(.cpp文件)? 12 51. 什么情况下类必须定义自己的复制构造函数? 12 52. 常量数据成员和静态常量数据成员有什么区别?如何初始化常量数据成员?如何初始化静态常量数据成员? 12 53. 什么是this指针?为什么要有this指针? 12 54. 复制构造函数的参数为什么一定要用引用传递,而不能用值传递? 12 55. 构造函数为什么要有初始化列表? 12 56. 如何区分++和--的前缀用法和后缀用法的载函数? 12 57. 类有几个默认的成员函数? 13 58. 什么是抽象类?定义抽象类有什么意义? 抽象类在使用上有什么限制? 13 59. 为什么要定义虚析构函数? 13 60. 试说明派生类对象的构造和析构次序。 13 61. 试说明虚函数和纯虚函数有什么区别 13 62. 基类指针可以指向派生类的对象, 为什么派生类的指针不能指向基类对象? 13 63. 如果一个派生类新增加的数据成员有一个对象成员,试描述派生类的构造过程 13 64. 为什么函数模板的使用与普通的函数完全一样, 而类模板在使用时还必须被实例化? 13 65. 类模板继承时的语法与普通的类继承有什么不同? 13 66. 什么是打开文件?什么是关闭文件?为什么需要打开和关闭文件? 14 67. 为什么要检查文件打开是否成功?如何检查? 14 68. ASCII文件和二进制文件有什么不同? 14 69. C++有哪4个预定义的流? 14 70. 什么时候用输入方式打开文件?什么时候应该用输出方式打开文件?什么时候该用app方式打开文件? 14 71. 哪些流操纵符只对下一次输入/输出有效?哪些流操纵符是一直有效直到被改变? 14 72. 什么叫做作用域?什么叫做局部变量? 什么叫做全局变量? 14
目 录 译者序 前言 第1章 对象的演化 1.1基本概念 1.1.1对象:特性十行为 1.1.2继承:类型关系 1.1.3多态性 1.1.4操作概念:OOP程序像什么 1.2为什么C++会成功 1.2.1较好的C 1.2.2采用渐进的学习方式 1.2.3运行效率 1.2.4系统更容易表达和理解 1.2.5“库”使你事半功倍 1.2.6错误处理 1.2.7大程序设计 1.3方法学介绍 1.3.1复杂性 1.3.2内部原则 1.3.3外部原则 1.3.4对象设计的五个阶段 1.3.5方法承诺什么 1.3.6方法应当提供什么 1.4起草:最小的方法 1.4.1前提 1.4.2高概念 1.4.3论述(treatment) 1.4.4结构化 1.4.5开发 1.4.6写 1.4.7逻辑 1.5其他方法 1.5.1Booch 1.5.2责任驱动的设计(RDD) 1.5.3对象建模技术(OMT) 1.6为向OOP转变而采取的策略 1.6.1逐步进入OOP 1.6.2管理障碍 1.7小结 第2章 数据抽象 2.1声明与定义 2.2一个袖珍C库 2.3放在一起:项目创建工具 2.4什么是非正常 2.5基本对象 2.6什么是对象 2.7抽象数据类型 2.8对象细节 2.9头文件形式 2.10嵌套结构 2.11小结 2.12练习 第3章 隐藏实现 3.1设置限制 3.2C++的存取控制 3.3友元 3.3.1嵌套友元 3.3.2它是纯的吗 3.4对象布局 3.5类 3.5.1用存取控制来修改stash 3.5.2用存取控制来修改stack 3.6句柄类(handleclasses) 3.6.1可见的实现部分 3.6.2减少复编译 3.7小结 3.8练习 第4章 初始化与清除 4.1用构造函数确保初始化 4.2用析构函数确保清除 4.3清除定义块 4.3.1for循环 4.3.2空间分配 4.4含有构造函数和析构函数的stash 4.5含有构造函数和析构函数的stack 4.6集合初始化 4.7缺省构造函数 4.8小结 4.9练习 第5章 函数载与缺省参数 5.1范围分解 5.1.1用返回值载 5.1.2安全类型连接 5.2载的例子 5.3缺省参数 5.4小结 5.5练习 第6章 输入输出流介绍 6.1为什么要用输入输出流 6.2解决输入输出流问题 6.2.1预先了解操作符载 6.2.2插入符与提取符 6.2.3通常用法 6.2.4面向行的输入 6.3文件输入输出流 6.4输入输出流缓冲 6.5在输入输出流查找 6.6strstreams 6.6.1为用户分配的存储 6.6.2自动存储分配 6.7输出流格式化 6.7.1内部格式化数据 6.7.2例子 6.8格式化操纵算子 6.9建立操纵算子 6.10输入输出流实例 6.10.1代码生成 6.10.2一个简单的数据记录 6.11小结 6.12练习 第7章 常量 7.1值替代 7.1.1头文件里的const 7.1.2const的安全性 7.1.3集合 7.1.4与C语言的区别 7.2指针 7.2.1指向const的指针 7.2.2const指针 7.2.3赋值和类型检查 7.3函数参数和返回值 7.3.1传递const值 7.3.2返回const值 7.3.3传递和返回地址 7.4类 7.4.1类里的const和enum 7.4.2编译期间类里的常量 7.4.3const对象和成员函数 7.4.4只读存储能力 7.5可变的(volatile) 7.6小结 7.7练习 第8章 内联函数 8.1预处理器的缺陷 8.2内联函数 8.2.1类内部的内联函数 8.2.2存取函数 8.3内联函数和编译器 8.3.1局限性 8.3.2赋值顺序 8.3.3在构造函数和析构函数里隐藏行为 8.4减少混乱 8.5预处理器的特点 8.6改进的错误检查 8.7小结 8.8练习 第9章 命名控制 9.1来自C语言静态成员 9.1.1函数内部的静态变量 9.1.2控制连接 9.1.3其他的存储类型指定符 9.2名字空间 9.2.1产生一个名字空间 9.2.2使用名字空间 9.3C++静态成员 9.3.1定义静态数据成员的存储 9.3.2嵌套类和局部类 9.3.3静态成员函数 9.4静态初始化的依赖因素 9.5转换连接指定 9.6小结 9.7练习 第10章 引用和拷贝构造函数 10.1C++的指针 10.2C+十的引用 10.2.1函数的引用 10.2.2参数传递准则 10.3拷贝构造函数 10.3.1传值方式传递和返回 10.3.2拷贝构造函数 10.3.3缺省拷贝构造函数 10.3.4拷贝构造函数方法的选择 10.4指向成员的指针(简称成员指针) 10.5小结 10.6练习 第11章 运算符载 1

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值