C方法有时优于C ++方法吗?

时间:2012-02-01 08:08:34

标签: c++ c oop procedural-programming

我最近一直在考虑这个问题。我们大多数人都清楚地意识到,在C中,为了创建结构,通常在其前面加上typedef,以避免在引用对象之前调用struct关键字。当然,C仅限于结构而不是类。为了弥补这一点,C倾向于使用专用于结构的全局函数来创建面向对象的方法

例如:

typedef struct{
    int foo;
    float bar;
    char* baz;
} SomeStruct;

Vs以上。

struct AnotherStruct {
    int foo;
    float bar;
    char* baz;
};
当在函数中声明该类型的对象时,

AnotherStruct必须在其前面具有前缀关键字struct。例如:

int main( ... )
{
   struct AnotherStruct obj1; //correct
   SomeStruct obj2; //correct
   struct SomeStruct obj3; //bad
   AnotherStruct obj4; //bad 
}

在面向对象的方法方面:

typedef struct {
    //member variables here
} SomeStruct;

SomeStruct* SomeStruct_New( int a, int b, int c )
{
    SomeStruct* obj = calloc( sizeof( SomeStruct ), 1 ); //not sure if that's correct -- been a while since I've used calloc.
    obj.a = a;
    obj.b = b;
    obj.c = c;
    return obj;
}

void SomeStruct_Free( SomeStruct* free )
{
    free( free );
}

这些函数很容易在没有包装器的情况下实现 - 我只是为了举例而使用它们。我的观点是,鉴于您已经可以在C ++中创建一个结构,它不需要typedef在没有struct关键字的情况下声明,并且使用与这些结构相关的非封装函数面向方法,我很想知道在C ++中C编码方法是否有任何优势,包括使用静态全局函数作为私有成员函数,以及将返回指向对象的指针的全局函数构造函数。

这主要是出于好奇,因为有时我觉得采取C方法只是为了接受它,但这可能只是一个优先事项。

4 个答案:

答案 0 :(得分:3)

很难理解问题的要点。在我看来,你的主要讯问是:

  • “简单”数据+功能

优于

  • 物体

在某些情况下。

不。相当于。

除了异常(!)之外,您在C ++中表达的任何代码都可以用C表示。这只是语法糖的问题,使C ++对应物更容易阅读。 在反对者加入潮流之前,可以用C模拟虚拟表格。

不过,我宁愿使用C ++。编译器检查封装(private),编译器驱动的重载选择,编译器 - 样板(模板)。它只是 语法糖,但是这种甜糖。

话虽如此:

class Foo {
  Foo() {}

  friend Foo build(int a, int b);
  friend int getA(Foo const& foo);
  friend int getB(Foo const& foo);

  int a;
  int b;
};

可以被认为是面向对象。

编辑simple and dummy example of polymorphism

#include <stdio.h>

// Interface
typedef void (*FunctionPrint)(void const*);

typedef struct {
  FunctionPrint print;
} PrinterInterface;

void print(void const* item, PrinterInterface const* pi) {
  (*pi->print)(item);
}

// Foo
typedef struct { int a; } Foo;

void printFoo(void const* arg) {
  Foo const* foo = (Foo const*)arg;
  printf("Foo{%d}\n", foo->a);
}

PrinterInterface const FooPI = { &printFoo };

// Bar
typedef struct { char* a; } Bar;

void printBar(void const* arg) {
  Bar const* bar = (Bar const*)arg;
  printf("Bar{\"%s\"}\n", bar->a);
}

PrinterInterface const BarPI = { &printBar };

// Main
int main() {
  Foo foo = { 1 };
  Bar bar = { "Hello, World!" };

  print(&foo, &FooPI);
  print(&bar, &BarPI);
}

结果:

Foo{1}
Bar{"Hello, World!"}

答案 1 :(得分:0)

据我所知,这种声明的存在只是因为一些常见的标题(主要来自OS API:想到windows.h或“xlib.h”)必须在C和C ++程序中使用,不可预知的C和C ++版本。

如果今天重写这样的API(注意:API本身,而不仅仅是接口),它们可能没有那些类型的声明。 是一种“混蛋编码”,它使API开发人员确定内存映射(当结构绑定到硬件或外部二进制格式时很重要)和“魔术数字定义”,它们从不在不同语言的不同标题中重复。

答案 2 :(得分:0)

不,我认为在C ++中没有任何理由可行。

您希望使用C方法的最明显的情况是中断和线程回调函数。但是那些可以写成C ++中的私有静态成员,这是首选。

通常,在极少数情况下,甚至从C或C ++中的函数返回指针也是有意义的。您的示例不是很好的OO,您强制类的用户在不需要时使用动态分配。在C中编写OO代码时,通常会将分配留给调用者。

当您不希望调用任何构造函数时,我可以在实时嵌入式编程中提出一些案例,因此完全避免使用类,但在这种情况下,您可能根本不会使用C ++。

答案 3 :(得分:0)

就在最近,我开始使用Horde3D来实现(或多或少)你所描述的内容。 在C ++内部实现,在C中公开一个简单的API。

这种方法对于那些像我一样希望通过外语界面重用引擎的人来说很有吸引力。我正在努力将引擎耦合到SWI-Prolog,并且由于Prolog不遵循OOP方向,因此使用(例如)OGRE接口没有任何好处。 OGRE有更多的功能,但简单也可以有他的优点......