当前位置:  编程技术>c/c++/嵌入式
本页文章导读:
    ▪探讨C语言中的回调函数      http://www.blogjava.net/huyi2006/articles/180169.html回调函数是一个程序员不能显式调用的函数;通过将回调函数的地址传给 调用者从而实现调用。回调函数使用是必要的,在我们想通过一个统一接口实.........
    ▪感悟(一)      通过第2章的习题4, 并结合这几年工作中处理编程任务的方法, 总结出了下面的一段话在分析根据菜谱烹饪菜肴的过程, 与编程方法的本质是一致的烤蓝莓松饼等同于一个编程任务, 菜谱中的这.........
    ▪[C++]《深度探索C++对象模型》读书笔记 - nontrivial default constructor      C++里,如果程序员没有显式的定义默认构造函数(default constructor),编译器会在需要的时候生成一个,也就是隐式地声明出来。隐式声明的默认构造函数有两种,一种是trivial(无用的) constructor,.........

[1]探讨C语言中的回调函数
    来源:    发布时间: 2013-10-14

http://www.blogjava.net/huyi2006/articles/180169.html

回调函数是一个程序员不能显式调用的函数;通过将回调函数的地址传给
调用者从而实现调用。回调函数使用是必要的,在我们想通过一个统一接口实现不

同的内容,这时用回掉函数非常合适。比如,我们为几个不同的设备分别写了不同
的显示函数:void TVshow(); void
ComputerShow(); void NoteBookShow()...等
等。这是我们想用一个统一的显示函数,我们这时就可以用回掉函数了。void
sho
w(void (*ptr)()); 使用时根据所传入的参数不同而调用不同的回调函数。

      不同的编程语言可能有不同的语法,下面举一个c语言中回调函数的例子,
其中一个回调函数不带参数,另一个回调函数带参数。

      例子1:
//Test.c
#include <stdlib.h>
#include
<stdio.h>
int Test1()
{
  int i;
  for (i=0; i<30; i++)

  {
printf("The %d th charactor is: %c\n", i, (char)('a' + i%26));

  }
  return 0;
}
int Test2(int num)
{
  int i;

  for (i=0; i<num; i++)
  {
   printf("The %d th charactor is:
%c\n", i, (char)('a' + i%26));

  }
  return 0;
}
void
Caller1(void (*ptr)())//指向函数的指针作函数参数
{
  (*ptr)();
}
void
Caller2(int n, int (*ptr)())//指向函数的指针作函数参数,这里第一个参数是为指向函数的指针服务的,
{
                                              //不能写成void Caller2(int (*ptr)(int
n)),这样的定义语法错误。
  (*ptr)(n);
  return;
}
int main()
{

  printf("************************\n");
  Caller1(Test1);
//相当于调用Test2();

  printf("&&&&&&************************\n");

  Caller2(30, Test2); //相当于调用Test2(30);
  return 0;
}

      以上通过将回调函数的地址传给调用者从而实现调用,但是需要注意的是带

参回调函数的用法。要实现回调,必须首先定义函数指针。函数指针的定义这里稍
微提一下。比如:
    int (*ptr)();
这里ptr是一个函数指针,其中(*ptr)的括号不能省略,因为
括号的优先级高于星号,那样就成了一个返回类型为整型的函数声明了

本文链接


    
[2]感悟(一)
    来源:    发布时间: 2013-10-14
通过第2章的习题4, 并结合这几年工作中处理编程任务的方法, 总结出了下面的一段话
在分析根据菜谱烹饪菜肴的过程, 与编程方法的本质是一致的
烤蓝莓松饼等同于一个编程任务, 菜谱中的这些指令就是要完成编程任务需要的操作过程。
每个单独的动作位于自己编号的段落中,就是编程过程中创建的函数或方法,而每个烹饪步骤中使用的原材料,烹饪工具就是函数的输入。
在所有步骤按照顺序执行结束后就是成品,也就完成了编程任务
整体是过程式的,而在每个过程中又可以面向对象。
 
概括一个编程任务的生命:
1. 分析任务包含的执行步骤
2.提炼步骤,为每个步骤选取输入,设置输出(如果有)
3.为步骤创建类,函数,完成步骤定义的动作。检测输入,完成输出
4.所有步骤定义完成后,按步骤顺序依次调用。
 
在开始编写代码的时候,要特别关注正确,简单,高效这三个基本原则.而程序的组织则体现了我们的编程思路,目前的手段主要是把一个大的任务分解为多个小任务
这一技术主要包括两类方法:抽象和分治. 在分治时,按照功能划分又是最常用的方法
 
使用函数的原因:
当需要将一部分计算任务独立实现的时候,可以将其定义为一个函数. 这样可以:
  • 实现计算逻辑的分离
  • 使代码更清晰(通过使用函数名)

  •     
[3][C++]《深度探索C++对象模型》读书笔记 - nontrivial default constructor
    来源:    发布时间: 2013-10-14

C++里,如果程序员没有显式的定义默认构造函数(default constructor),编译器会在需要的时候生成一个,也就是隐式地声明出来。

隐式声明的默认构造函数有两种,一种是trivial(无用的) constructor,什么都不做;另一种是nontrival constructor,编译器合成的是后者。

在四种情况下,编译器需要合成nontrival constructor:

1. 带有"Default Constructor"的成员类对象

class A {public: A(), ... };

class B {public: A a;};

int f()
{
B b; //此处须调用B的默认构造函数
}

因为B::a是一个member object,且其class A拥有default constructor,所以编译器在需要调用B的默认构造函数时,会为B生成如下的默认构造函数

inline B::b()
{
// C++伪码
a.A::A(); // 调用a的默认构造函数
}

但需要注意的是,编译器产生的默认构造函数不会初始化基本类型的成员变量。
如果class B中有int类型的变量,其值不会被默认构造函数初始化为0。

还有一种情况,如果class B已经拥有一个默认构造函数,但其中并未对其对象成员进行初始化,如下例:

class B {public: A a, int num};

B::B() {num = 0}

对于这种情况,编译器会扩张已有的constructor,将对象成员的构造过程安插在user code前,像这样:

B::B()
{
a.A::A(); // 插入的compiler code
num = 0; // user code
}

 另外还需注意的是,编译器所安插的代码会按照“对象在class中的声明顺序”来调用各个constructor,在user code前。

2. "带有Default Constructor"的Base Class

如果一个class派生自一个“带有default constructor”的base class,那个这个class的default constructor需要被编译器合成出来,以调用上一层base class的default constructor。
很多人都了解“子类在调用构造函数时,会先调用父类的构造函数”,这正是因为编译器在我们定义的constructor中进行了上述扩展。

3. "带有Virtual Function"的Class

虚函数表(vtbl)的相关实现机制超出了本文的范围,读者可找相关文章或书藉来学习。

如果class或继承的base class中声明了virtual function(虚函数),编译器会对default constructor进行扩张:
  1. 为class产生一个virtual function table。
  2. 为每个class object创建一个额外的point member(vptr),指向相应的virtual function table。

此外,编译器还会对“虚函数的调用操作”进行修改,如b.f(),会被改为:

(*(b.vptr[1])) (&b);
// 1表示函数f()在vtbl中的索引值,(b.vptr[1])返回了函数f()的地址。
// &b表示交给f()函数调用的this指针,这里涉及到了name magling的知识,读者可自行搜索。

4. "带有一个Virtual Base Class"的Class

虚基类(virtual Base Class)指多继承时,某个base class可能会出现在多个继承路径上。为了防止该基产生多个拷贝,可将基类的继承声明为虚拟的,这样就只会继承基类的一份拷贝。

虽然这样base class只有一份拷贝,但在多态环境下,编译器无法固定”经由某个指针类型而存取的base class中的成员”的实际偏移位置,因为其实际类型是可以改变的。
cfont对这个问题的解决方法是:在derived class object的每一个virtual base class中安插一个指针__vbcX,所有经由引用或指针对virtual base class的操作都可以通过该指针来完成。

而对__vbcX的初始化,正是编译器在default constructor中进行的扩张。

 

对于这4种情况以外的,且没有声明default constructor的class,我们说它们拥有的是trivial default constructors,实际上它们并没有被合成出来。
所以,“任何class如果没有定义default constructor,都会被生成一个出来”这种说法是错误的。

最后还有一点要注意,生成出来的nontrivial default constructor只对类对象进行初始化,或基本类型(int, double, string)的成员变量还需要程序员来显式的进行初始化。

本文链接


    
最新技术文章:
▪C++单例模式应用实例
▪C++设计模式之迭代器模式
▪C++实现动态分配const对象实例
▪C++设计模式之中介者模式
▪C++设计模式之备忘录模式
▪C++插入排序算法实例
▪C++冒泡排序算法实例
▪C++选择排序算法实例
▪C++归并排序算法实例
▪C++设计模式之观察者模式
▪C++中复制构造函数和重载赋值操作符总结
▪C++设计模式之状态模式
▪C++设计模式之策略模式
▪C++设计模式之访问者模式
▪C++设计模式之模板方法模式
▪C++实现下载的代码
▪C++模板之特化与偏特化详解
▪C++实现查壳程序代码实例
▪C语言、C++内存对齐问题详解
▪C语言、C++中的union用法总结
编程技术其它 iis7站长之家
▪C++中memcpy和memmove的区别总结
▪C++通过TerminateProess结束进程实例
▪C++内存查找实例
▪C++实现CreatThread函数主线程与工作线程交互的...
▪C++设计模式之桥接模式
▪C++中关键字Struct和Class的区别
▪C++设计模式之组合模式
▪C++ COM编程之什么是组件?
▪C++ COM编程之什么是接口?
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3