码迷,mamicode.com
首页 > 编程语言 > 详细

第4章 为什么要C++

时间:2016-06-01 18:01:47      阅读:232      评论:0      收藏:0      [点我收藏+]

标签:

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
View Code
技术分享
#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");
}
View Code
技术分享
#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

 
View Code
#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++的基本方法就是把函数加入结构内部,结构的这种类型形成了抽象数据类型,用这种结构创建的变量称为这个类型的对象或实例。

第4章 为什么要C++

标签:

原文地址:http://www.cnblogs.com/hinice/p/5534594.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!