我知道这听起来很傻,我知道C不是面向对象的语言.
但有没有办法在C中实现动态方法调度?我考虑过函数指针,但没有得到完整的想法.
我怎么能实现这个?
假设我有一些结构定义如下:
struct foo { int a; };
struct bar { struct foo r; int b; };
struct baz { struct bar z; int c; };
Run Code Online (Sandbox Code Playgroud)
C标准是否保证以下代码严格符合要求?
struct baz x;
struct foo *p = (void *)&x;
assert(p == &x.z.r);
Run Code Online (Sandbox Code Playgroud)
这种结构的动机是提供一致的编程习惯用于转换为已知兼容的指针类型.
现在,这就是C所说的结构及其初始成员如何可转换:
在结构对象中,非位字段成员和位字段所在的单元具有按声明顺序增加的地址.指向适当转换的结构对象的指针指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然.结构对象中可能存在未命名的填充,但不是在其开头.
C.11§6.7.2.115
这就是void指针转换的内容:
指针
void可以转换为指向任何对象类型的指针.指向任何对象类型的指针可以转换为指向void和返回的指针; 结果应该等于原始指针.
C.11§6.3.2.31
这就是关于在对象指针类型之间进行转换的说法:
指向对象类型的指针可以转换为指向不同对象类型的指针.如果对于引用的类型,结果指针未正确对齐(68),则行为未定义.否则,当再次转换回来时,结果将等于原始指针.
68)一般来说,''正确对齐''这个概念是传递性的:如果一个指向类型A的指针正确地对齐指向类型B的指针,而指针又指向一个指向类型C的指针,那么指向类型的指针对于指向类型C的指针,A正确对齐
.C.11§6.3.2.37
我从上面的理解是,通过转换将对象指针void *转换为不同类型的对象指针是完全正确的.但是,我得到的评论表明不然.
在不同的StackExchange中,以下算法(基于算术编码)被提出作为生成7面骰子结果的有效方法,当给出的所有内容都是6面骰子时:
int rand7()
{
static double a=0, width=7; // persistent state
while ((int)(a+width) != (int)a)
{
width /= 6;
a += (rand6()-1)*width;
}
int n = (int)a;
a -= n;
a *= 7; width *= 7;
return (n+1);
}
Run Code Online (Sandbox Code Playgroud)
不是一个真正的数学家,我会尽力解释这个算法是如何工作的:
在每次调用开始时rand7(),width比率为7 s/6 t,并且a是非负值,其属性a + width位于基本情况之后的区间[0,7]中.进入while循环时,width是可以添加的最大值a.如果floor(a + width)不同floor(a),则添加{0,width*1/6,width*1/3,width*1/2,width*2/3,width*5/6} 的随机选择 …
尝试重载函数和函数模板时,我得到不同的行为.功能:
void foo(int)
{
std::cout << "int";
}
void foo(char)
{
std::cout << "char";
}
Run Code Online (Sandbox Code Playgroud)
foo(42)是int.但对于功能模板:
template <int T>
void bar()
{
std::cout << "int T";
}
template <char T>
void bar()
{
std::cout << "char T";
}
Run Code Online (Sandbox Code Playgroud)
bar<42>()是暧昧的电话.即使我使用char,也会发生这种情况bar<'a'>().为什么一个工作而另一个工作?
如何声明一个指向具有相同参数的函数的函数指针,并返回指向具有相同参数的函数的指针.
ie
funcPtr指向func1(int a, int b),并func1返回指向另一个函数的指针func2(int a, int b).func2还返回一个具有相同签名的函数指针func1.
TYPE funcPtr = func1;
funcPtr = funcPtr(0, 1);
Run Code Online (Sandbox Code Playgroud)
如何申报funcPtr?应该TYPE是什么?
我正在这里阅读这段代码(中文).有一段关于在C中测试全局变量的代码.该变量a已在文件t.h中定义,该文件已包含两次.在文件中foo.c定义了一个struct b带有一些值和一个main函数.在main.c文件中,定义了两个没有初始化的变量.
/* t.h */
#ifndef _H_
#define _H_
int a;
#endif
/* foo.c */
#include <stdio.h>
#include "t.h"
struct {
char a;
int b;
} b = { 2, 4 };
int main();
void foo()
{
printf("foo:\t(&a)=0x%08x\n\t(&b)=0x%08x\n
\tsizeof(b)=%d\n\tb.a=%d\n\tb.b=%d\n\tmain:0x%08x\n",
&a, &b, sizeof b, b.a, b.b, main);
}
/* main.c */
#include <stdio.h>
#include "t.h"
int b;
int c;
int main()
{
foo();
printf("main:\t(&a)=0x%08x\n\t(&b)=0x%08x\n
\t(&c)=0x%08x\n\tsize(b)=%d\n\tb=%d\n\tc=%d\n", …Run Code Online (Sandbox Code Playgroud) 有人可以提供一些最简单的TAILQ使用示例,可以在Linux系统库中解释c,可以在Linux中使用gcc编译吗?
因此,在接受James Kanze和Loki Astari关于C联动的培训时,我对此感到疑惑:
extern "C" int foo1 (void (*)());
extern "C" { int foo2 (void (*)()); }
Run Code Online (Sandbox Code Playgroud)
在我上学之后,我认为必须foo1只使用带有C++链接foo2的函数指针,而只需要带有C链接的函数指针.我的理解是否正确?C++标准中是否有特定的参考资料来解释上述示例中的差异?
编辑:为了让每个人都能更方便地遵循这里的一个带有C++ 11草案标准相关部分的pastebin.
我是iPhone编程的新手.我想得到图像的高度和宽度,所以我可以相应地设置框架UIImageview.任何建议如何获得图像的原始大小(宽度和高度)?
这基本上是对早期问题的跟进(不是我提出的,但我对答案很感兴趣).
问题是: 为什么编译器/链接器无法解析派生类对虚函数的调用?在这种情况下,派生类是具有可变参数的模板类,该参数对同一模板类多次应用多次继承(对于可变参数中的每个类型一次).
在下面的具体示例中,派生类是JobPlant,并且正在调用它Worker.调用抽象work()方法无法链接,同时调用workaround()链接并以预期方式执行.
这些是ideone所示的链接失败:
/home/g6xLmI/ccpFAanK.o: In function `main':
prog.cpp:(.text.startup+0x8e): undefined reference to `Work<JobA>::work(JobA const&)'
prog.cpp:(.text.startup+0xc9): undefined reference to `Work<JobB>::work(JobB const&)'
prog.cpp:(.text.startup+0xff): undefined reference to `Work<JobC>::work(JobC const&)'
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
请点击此链接以演示变通方法的工作原理.
Job是一个抽象基类,它具有关联的派生类.Work是一个执行作业的抽象模板类.Worker是一个标识JOB并执行它的模板(struct而不是class纯粹减少语法混乱):
struct Job { virtual ~Job() {} };
struct JobA : Job {};
struct JobB : Job {};
struct JobC …Run Code Online (Sandbox Code Playgroud)