第4章 为什么要C++

1.为了提高生产效率,我们使用别人代码库,库就是别人写好的一些代码,按照某种方式包装在一起。

2.一个库通常以一个头文件的形式给出一组函数,但是通常的话还有一些比函数(行为,动作)更重要的东西,一些特征属性(颜色,大小,质量),他们是以数据的形式表现的。在C库的头文件中,我们就定义可一个struct来表示这些特征属性。在C库中,都是一组struct和作用在它们之上的一组函数。

3.动态内存分配  在C++中用new Type 返回Type型的指针, 数组的释放delete []myarray  ;new int myarray[10];

4.在C中,编译器会猜测一个函数像什么(这个特征不严格),但是他不会猜测一个结构,所有使用库结构的地方,必须加入头文件。

5.编译的时候,他是逐个单元编译的,它只知道这个单元,这个时候包含的头文件给出的声明信息非常重要,他会影响程序的翻译。比如一个头文件中声明了一个函数void f(float);这个时候,在这个文件中,如果一个整型调用这个函数,编译器根据声明就会提升。如果没有包含声明,C编译器会自己假设有一个函数void f(int);最后会链接到void f(float)么?可以通过_f_float与_f_int区别么????(C中都翻译为_f)

6.调用链接不正确很难发现,如果有几个厂家提供库中有相同名字的不同函数,程序开发就不好处理。名字冲突是一个问题。我们的目标是能够准确的链接和翻译每一个单元。

7.第一个,给函数翻译加参数,第二个,C++,把函数和结构相连,写入结构。对象的思想就出现了。C++就是把函数当做结构的一个成员。而且,这些函数自动的知道的结构地址。C++要求必须有声明。

8.作用域解析运算符::      CStack::init()

9.在C++中,头文件的声明是必须的,不能调用未声明的函数。而且结构中的函数使用成员时,隐藏的是知道结构的地址this(它产生struct的地址)。

10.在C++中允许将任何类型的指针赋值给void*(这是void*的意图,用来存放任何类型的指针),但是不能把void*赋值给其他类型的指针。因为这样就有调用可能struct逻辑不存在的成员函数。

11.在C中。struct只是分装了数据,他是数据的包,这样,编程起来方便了很多,但是C++把函数放入这个结构包中,就很像我们思维中的事物的概念了。它既描述了事物的特征属性,又能描述这个事物的行为。这样就形成了一个对象的概念,对象是一个独立的,捆绑的实体,有自己的属性和行为。

12.C++把函数写入结构的是基于对象,而不是面向对象的,这个问题就是面向对象的各种语言之间的范畴问题。

13.抽象数据类:是一种区别于基本内嵌的类型的一种概念,其实float也看以看做是抽象的,它有尾数,符号位,指数,这个只是一种相对的概念,我们的现实中的问题大部分都是抽象的复杂的数据类型。C++的捆绑封装形成的这种结构,带有他自身的一些行为函数,就形成了一个数据类型的概念。编译器可以把它可以根据这些检查这个类型个的应用,我们就把问题提升到一个更高的问题讨论了。

14.对象的细节

  对象应当多大和它应当像什么?对象和C的struct一样,一个对象的大小是它的所有数据成员的大小,不包括函数。有时候会有些许的调整,为了边界对齐和寻址方便快捷。

15.头文件,正确的组织代码和头文件是很重要的,头文件中,只有声明,不包含代码和其他创建变量之类的,因为它会被包含到多个翻译单元中,如果一个标识符被多次定义,就会编译错误。但是可以在头文件中定义文件静态变量,这种情况是允许的(但是每个包含头文件的编译单元中都会有一个这个静态变量的拷贝,其实是不同的东西,static是文件内有效的意思,不同的文件中可以有相同的标识符的static变量)。就是我们不能引起歧义,要遵从编译器的规则。

16.重声明函数是可以的,只要两个函数的声明匹配就可以。但是不允许重声明结构体,那样的话就是可以使用给不同的类型定义相同的名字,这显然是错误的,应为一个class A这个类型必须是固定的,不然没法链接,这个书中写的是机器人翻译。然后这个时候就引出了#ifdef#ifndef#endif预处理。对于包含接头的头文件,应当检查这个头文件是不是已经包含在特定的CPP文件中了。这个需要测试预处理器的标记来检查,如果这个标记没有,则这个文件没有被包含,应当设置他,并声明这个结构。如果这个标志已经有了,这表示已经声明了这个结构类型,所以应当忽略这段声明它的代码。

  #ifndef HEAD_FLAG

  #define HEAD_FLAG

  //类型在此间声明

  #endif

17.头文件中的名称空间

  在头文件中不要使用,一旦使用等于是所有包含此文件的cpp都对可以使用这个空间的名称,这雨名称空间的保护初衷是相悖的。

18.嵌套结构:结构中包含小的结构

  

//下堆栈,结构链表,嵌套结构
#ifndef STACK_H
#define STACK_H

struct Stack{
    struct Link{
        void* data;
        Link* next;
        void initialize(void* dat,Link* nxt);
    }*head;
    void initialize();
    void push(void* data);
    void* peek();
    void* pop();
    void cleanup();
};

#endif

#include"Stack.h"
#include"required.h"
using namespace std;

void Stack::Link::initialize(void* dat,Link* nxt)
{
    data = dat;
    next = nxt;
}

void Stack::initialize()
{
    head = 0;
}

void Stack::push(void* dat)
{
    Link* newLink = new Link;
    newLink->initialize(dat,head);
    head = newLink;
}
// /*
void* Stack::peek()
{
    require(head!=0,"Stack empty");
    return head->data;
}
// */

void* Stack::pop()
{
    if(head==0) return 0;
    void* result = head->data;
    Link* oldHead =head;
    head = head->next;
    delete oldHead;
    return result;
}

void Stack::cleanup()
{
    require(head==0,"Stack not empty");
}

#ifndef REQUIRE_H
#define REQUIRE_H
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <string>

inline void require(bool requirement, const std::string& msg = "Requirement failed")
{
  using namespace std;
  if (!requirement)
  {
    fputs(msg.c_str(), stderr);
    fputs("\n", stderr);
    exit(1);
  }
}

inline void requireArgs(int argc, int args, const std::string& msg =  "Must use %d arguments")
{
  using namespace std;
   if (argc != args + 1)
   {
     fprintf(stderr, msg.c_str(), args);
     fputs("\n", stderr);
     exit(1);
   }
}

inline void requireMinArgs(int argc, int minArgs, const std::string& msg = "Must use at least %d arguments")
{
  using namespace std;
  if(argc < minArgs + 1)
  {
    fprintf(stderr, msg.c_str(), minArgs);
    fputs("\n", stderr);
    exit(1);
  }
}

inline void assure(std::ifstream& in, const std::string& filename = "")
{
  using namespace std;
  if(!in)
  {
    fprintf(stderr, "Could not open file %s\n",
      filename.c_str());
    exit(1);
  }
}

inline void assure(std::ofstream& out, const std::string& filename = "")
{
  using namespace std;
  if(!out)
  {
    fprintf(stderr, "Could not open file %s\n",
      filename.c_str());
    exit(1);
  }
}

#endif

#include "Stack.h"
#include "required.h"//#include "./required.h"    //ok  Linux//#include "../required.h"    //error
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char* argv[]) {
    requireArgs(argc, 1); // File name is argument
    ifstream in(argv[1]);
    assure(in, argv[1]);
    Stack textlines;
    textlines.initialize();        //初始化head==0
    string line;
    // Read file and store lines in the Stack:
    while(getline(in, line))
        textlines.push(new string(line));
        // Pop the lines from the Stack and print them:
    string* s;
    while((s = (string*)textlines.pop()) != 0)
    {
        cout << *s << endl;
        delete s;        //释放new string(line) 的内存
    }
    textlines.cleanup();
} ///:~

19.全局作用域解析    前面加  ::var  ::fun()

  var = 1;  fun() 这种事调用默认的局部成员和函数

20.C++的基本方法就是把函数加入结构内部,结构的这种类型形成了抽象数据类型,用这种结构创建的变量称为这个类型的对象或实例。

时间: 2024-11-07 20:49:53

第4章 为什么要C++的相关文章

C#认证第一章1 题 11题

C#第一章第一题 C#认证第一章  11题

C#图解教程 第二十四章 反射和特性

反射和特性元数据和反射Type 类获取Type对象什么是特性应用特性预定义的保留的特性Obsolete(废弃)特性Conditional特性调用者信息特性DebuggerStepThrough 特性其他预定义特性有关应用特性的更多内容多个特性其他类型的目标全局特性自定义特性声明自定义特性使用特性的构造函数指定构造函数使用构造函数构造函数中的位置参数和命名参数限制特性的使用自定义特性的最佳实践访问特性使用IsDefined方法使用GetCustomAttributes方法 Note 类的元数据包含

【机器学习实战】第2章 K-近邻算法(k-NearestNeighbor,KNN)

第2章 k-近邻算法 <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=default"></script> KNN 概述 k-近邻(kNN, k-NearestNeighbor)算法主要是用来进行分类的. KNN 场景 电影可以按照题材分类,那么如何区分 动作片 和 爱情片 呢? 动作片:打斗次数更多 爱情片

计算机网络安全第一章

计算机网络不安全因素:偶发因素.自然因素.认为因素(被动攻击.主动攻击.邻近攻击.内部人员攻击.分发攻击) 不安全的主要原因: 1.互联网具有不安全性:开放的网络,国际性的网络,自由性的网络 2.操作系统存在的安全问题:操作系统软件自身的不安全性,留下"后门".操作 系统体系结构造成的不安全隐患.操作系统可以创建进程.操作系统的无口令入口及隐蔽通道 3.数据安全问题 4.传输线路安全问题 5.网络应用存在的安全问题 6.网络安全管理问题 计算机网络安全是一门涉及计算机科学.网络技术.通

数据库系统实现 第六章 查询执行

第六章 查询执行 查询执行也就是操作数据库的算法 一次查询的过程: 查询-->查询编译(第七章)-->查询执行(第六章)-->数据 查询编译预览 查询编译可以分为三个步骤: a)分析:构造分析树,用来表达查询和它的结构 b)查询重写,分析树被转化为初始查询计划,通常是代数表达式,之后初始的查询计划会被优化为一个时间更小的计划 c)物理计划生成,将查询计划转化成物理的计划, 为了选择更好的查询计划,需要判断 1)查询哪一个代数的等价形式是最有效的 2)对选中形式的每一个操作,所使用的算法选

Java编程思想读书笔记_第三章

本章提到的关于==的部分,一个完整的实验如下: 1 class Test { 2 public static void main(String[] args) { 3 Integer i = new Integer(47); 4 Integer j = new Integer(47); 5 Integer i1 = 47; 6 Integer j1 = 47; 7 int i2 = new Integer(47); 8 int j2 = new Integer(47); 9 int i3 = 4

第九章、文件与文件系统的压缩与打包

1. 压缩文件的用途与技术 2. Linux 系统常见的压缩命令 2.1 compress 2.2 gzip, zcat 2.3 bzip2, bzcat 3. 打包命令: tar 4. 完整备份工具:dump, restore 5. 光盘写入工具 5.1 mkisofs:创建映像档 5.2 cdrecord:光盘烧录工具 6. 其他常见的压缩与备份工具 6.1 dd 6.2 cpio 7. 重点回顾 1. 压缩文件的用途与技术 2. Linux 系统常见的压缩命令 压缩文件的扩展名大多是:『*

《TCP/IP具体解释》读书笔记(22章)-TCP的坚持定时器

TCP通过让接收方指明希望从发送方接收的数据字节数(即窗体大小)来进行流量控制. 假设窗体大小为0会发生什么情况呢?这将有效阻止发送方传送数据,直到窗体变为非0为止. ACK的传输并不可靠,也就是说,TCP不正确ACK报文段进行确认,TCP仅仅确认那些包括有数据的ACK报文段. 1.坚持定时器 假设一个场景:假设一个确认丢失了,则两方就有可能由于等待对方而使连接终止,接收方等待接收数据(由于它已经向发送方通告了一个非0的窗体),而发送方在等待同意它继续发送数据的窗体更新.为防止这种死锁情况的发生

第三章随笔

本章为软件工程师的成长,主要介绍了评价软件工程师水平的主要方法,技能的反面,TSP对个人的要求. 软件开发流程:软件开发流程包括团队的流程,也包括个人的流程 初级软件工程师有几方面成长: 1.积累软件开发相关的知识,提升技术技能2.积累问题领域的知识和经验3.对通用的软件设计思想和软件工程思想的理解4.提升职业技能5.实际成果 衡量软件开发的工作量和质量的因素: 1.项目/任务有多大2.花了多少时间3.质量如何4.是否按时交付 相对来说,交付时间的平均时间反应平均水平,而标准方差更为重要,在团队

java第15章示例代码

import java.util.Scanner; /** * * @author asus第15章示例代码1 全桂群2017.4.9 * */public class Registter { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Scanner input = new Scanner(System.in); String uname, pw