📄 00000003.htm
字号:
<HTML><HEAD> <TITLE>BBS水木清华站∶精华区</TITLE></HEAD><BODY><CENTER><H1>BBS水木清华站∶精华区</H1></CENTER> <BR>== Part 4/4 ============================ <BR> <BR>comp.lang.c++ Frequently Asked Questions list (with answers, fortunately). <BR>Copyright (C) 1991-96 Marshall P. Cline, Ph.D. <BR>Posting 4 of 4. <BR>Posting #1 explains copying permissions, (no)warranty, table-of-contents, etc <BR> <BR>======================================= <BR>■□ 第17节:和 C 连结/和 C 的关系 <BR>======================================= <BR> <BR>Q105:怎样从 C++ 中呼叫 C 的函数 "f(int,char,float)"? <BR> <BR>告诉 C++ 编译器说:它是个 C 的函数: <BR> extern "C" void f(int,char,float); <BR> <BR>确定你有 include 进来完整的函数原型 (function prototype)。一堆 C 的函数可 <BR>以用大括号框起来,如下: <BR> <BR> extern "C" { <BR> void* malloc(size_t); <BR> char* strcpy(char* dest, const char* src); <BR> int printf(const char* fmt, ...); <BR> } <BR> <BR>======================================== <BR> <BR>Q106:怎样才能建一个 C++ 函数 "f(int,char,float)",又能被 C 呼叫? <BR> <BR>想让 C++ 编译器知道 "f(int,char,float)" 会被 C 编译器用到的话,就要用到前 <BR>一则 FAQ 已详述的 "extern C" 语法。接著在 C++ 模组内定义该函数: <BR> <BR> void f(int x, char y, float z) <BR> { <BR> //... <BR> } <BR> <BR>"extern C" 一行会告诉编译器:送到 linker 的外部资讯要采用 C 的呼叫惯例及签 <BR>名编码法(譬如,前置一个底线)。既然 C 没有多载名称的能力,你就不能让 C 程 <BR>式能同时呼叫得到多载的函数群。 <BR> <BR>警告以及实作相关事项: <BR> * 你的 "main()" 应该用 C++ 编译之(为了静态物件的初始化)。 <BR> * 你的 C++ 编译器应该能设定连结的程序(为某些特殊的程式库)。 <BR> * 你的 C 和 C++ 编译器可能要是同一个牌子的,而且是相容的版本(亦即:有相 <BR> 同的呼叫惯例等等)。 <BR> <BR>======================================== <BR> <BR>Q107:为什麽 linker 有这种错误讯息:C/C++ 函数被 C/C++ 函数呼叫到? <BR> <BR>看前两则 FAQs 关於 extern "C" 的使用。 <BR> <BR>======================================== <BR> <BR>Q108:该怎麽把 C++ 类别的物件传给/传自 C 的函数? <BR> <BR>例子: <BR> <BR> /****** C/C++ header file: Fred.h ******/ <BR> #ifdef __cplusplus /*"__cplusplus" is #defined if/only-if <BR> compiler is C++*/ <BR> extern "C" { <BR> #endif <BR> <BR> #ifdef __STDC__ <BR> extern void c_fn(struct Fred*); /* ANSI-C prototypes */ <BR> extern struct Fred* cplusplus_callback_fn(struct Fred*); <BR> #else <BR> extern void c_fn(); /* K&R style */ <BR> extern struct Fred* cplusplus_callback_fn(); <BR> #endif <BR> <BR> #ifdef __cplusplus <BR> } <BR> #endif <BR> <BR> #ifdef __cplusplus <BR> class Fred { <BR> public: <BR> Fred(); <BR> void wilma(int); <BR> private: <BR> int a_; <BR> }; <BR> #endif <BR> <BR>"Fred.C" 是个 C++ 模组: <BR> <BR> #include "Fred.h" <BR> Fred::Fred() : a_(0) { } <BR> void Fred::wilma(int a) : a_(a) { } <BR> <BR> Fred* cplusplus_callback_fn(Fred* fred) <BR> { <BR> fred->wilma(123); <BR> return fred; <BR> } <BR> <BR>"main.C" 是个 C++ 模组: <BR> <BR> #include "Fred.h" <BR> <BR> int main() <BR> { <BR> Fred fred; <BR> c_fn(&fred); <BR> return 0; <BR> } <BR> <BR>"c-fn.c" 是个 C 模组: <BR> <BR> #include "Fred.h" <BR> void c_fn(struct Fred* fred) <BR> { <BR> cplusplus_callback_fn(fred); <BR> } <BR> <BR>把指向 C++ 物件的指标传到/传自 C 的函数,如果传出与收回的指标不是“完全相 <BR>同”的话,就会失败。譬如,不要传出一个基底类别的指标却收回一个衍生类别的指 <BR>标,因为 C 编译器不懂该怎麽对多重及虚拟继承的指标做转型。 <BR> <BR>======================================== <BR> <BR>Q109:C 的函数能不能存取 C++ 类别的物件资料? <BR> <BR>有时可以。 <BR> <BR>(请先读一读前一则关於和 C 函数间传递 C++ 物件的 FAQ。) <BR> <BR>你可以安全地从 C 函数中存取 C++ 物件的资料,只要 C++ 的物件类别: <BR> * 没有虚拟函数(包含继承下来的虚拟函数). <BR> * 所有资料都在同一个存取等级中 (private/protected/public). <BR> * 完全被包含的子物件中也都没有虚拟函数. <BR> <BR>如果 C++ 类别有任何基底类别(或是任何被完全包含的子物件中有基底类别)的话 <BR>,技术上来说,存取该资料没有可携性的,因为语言没规定在继承之下的类别配置是 <BR>什麽样子。不过经验上,所有 C++ 编译器的做法都一样:基底类别物件先出现(在 <BR>多重继承之下,则由左到右排列之),子物件次之。 <BR> <BR>还有,如果类别(或是任何基底类别)含有任何虚拟函数,你时常可以(但不是一直 <BR>都可以)假设有一个 "void*" 出现在物件第一个虚拟函数之所在,或是在该物件的 <BR>第一个 word 那里。同样的,语言对它也没规定到,但这似乎是「大家」都采取的做 <BR>法。 <BR> <BR>如果该类别有任何虚拟基底类别,情况会更复杂而且更没有可携性。常见的做法是: <BR>让物件最後才包含基底类别之物件 (V)(不管 "V" 在继承阶层中在哪儿出现),物 <BR>件的其他部份则以正常的次序出现。每个有 V 这个虚拟基底类别的衍生类别,实际 <BR>上都有个“指标”指向最後一个物件的 V 的部份。 <BR> <BR>======================================== <BR> <BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -