在isocpp.org中是否还有其他一些执行此示例的方法?

时间:2015-09-21 20:39:49

标签: c++ c

我尝试在this link in isocpp.org的第二个常见问题解答中编译并链接第二个示例(见下文)。

  

当然,这仅适用于非成员函数。如果你想   从C调用成员函数(包括虚函数),您需要   提供一个简单的包装。例如:

// C++ code:
class C {
    // ...
    virtual double f(int);
};
extern "C" double call_C_f(C* p, int i) // wrapper function
{
    return p->f(i);
}
     

现在可以像这样使用C :: f():

/* C code: */
double call_C_f(struct C* p, int i);
void ccc(struct C* p, int i)
{
    double d = call_C_f(p,i);
    /* ... */
}

经过几次试验,我成功地在VS2015中执行了这个例子。但是我仍然不相信我必须在extern "C" struct C *p = &c;中使用的声明other.cpp(我根本无法使代码与除此之外的任何东西一起工作)。请注意,C ++编译器会针对所提到的声明发出以下警告:

  

警告C4099:'C':使用现在看到的'class'首次看到的类型名称   '结构'

main.c是使用C编译器编译的,other.cpp是使用C ++编译器编译的。

的main.c

/* C code: */

#include <stdio.h>
extern struct C *p;
double call_C_f(struct C* p, int i);

void ccc(struct C* p, int i)
{
    double d = call_C_f(p, i);
    printf("%f", d);

}

int main()
{
    ccc(p, 1);
}

other.cpp

// C++ code:
class C {
public:
    virtual double f(int i) { return i; };
} c;

extern "C" struct C *p = &c;    // This is the declaration that I'm concerned about
                                // Is it correct?

extern "C" double call_C_f(C* p, int i) // wrapper function
{
    return p->f(i);
}

1 个答案:

答案 0 :(得分:0)

extern "C" struct C *p = &c行是恕我直言,而不是真正有用。在同一个C ++编译单元中,首先将C声明为类,然后是结构。正如在that other question中对refs的评论中已经说过的那样,使用struct声明一次类,使用class声明一次可能会导致C ++代码中的错误问题。

它没用,因为C不是POD结构(它包含方法,甚至是虚拟结构),它不能从C作为结构使用,实际上你只使用指向C代码的C作为一个不透明的指针。

所以该行应写成:

extern "C" class C *p = &c;

向编译器声明您正在定义指向类C的指针,并指向名为p的外部链接,指向c。从C ++角度完美定义。

接下来从C的角度来看,你声明了extern指针p,指向一个未定义的struct C. C只允许你使用它几乎是一个void指针,这意味着你可以影响它并将它传递给函数,但p->xxx会导致错误,因为struct C未在该编译单元中完全声明。

事实上,以下代码与您的代码完全相同,没有任何警告:

的main.c

/* C code: */

#include <stdio.h>
extern struct D *p;
double call_C_f(struct D* p, int i);

void ccc(struct D* p, int i)
{
    double d = call_C_f(p, i);
    printf("%f", d);

}

int main()
{
    ccc(p, 1);
    return 0; /* never return random value to environment */
}

other.cpp

// C++ code:
class C {
public:
    virtual double f(int i) { return i; };
} c;

extern "C" C *p = &c;

extern "C" double call_C_f(C* p, int i) // wrapper function
{
    return p->f(i);
}

struct D的使用不是拼写错误。当然我应该使用struct C来避免让读者感到困惑,但对于编译器来说,不是链接器也不是问题:main.c中的p只是一个指向不完全不透明的指针声明结构。这就是为什么,通常将这样的不透明指针声明为void *