0

How can one create a Haskell/C++ style constructor in C? Also, once I have this new object how can I define operations in it (such as LinkedList/Tree)?

user207421
  • 305,947
  • 44
  • 307
  • 483
  • 7
    What on earth does "Haskell/C++ style constructor" even mean? The term "constructor" is used for completely different things in those languages. – C. A. McCann Jun 01 '11 at 17:32
  • 4
    ... and why is the question tagged with "Java" anyway? – ignis Jun 01 '11 at 17:47
  • 1
    @ignis: Because... Java constructors clearly have at least as much in common with constructors in Haskell and C++ as the latter do with each other, I guess. – C. A. McCann Jun 01 '11 at 17:59
  • 1
    Mm, they clearly do not. Java and C++ are curly-braced, share part of the syntax of the control flow structures, have some other things in common, but *nothing more*. – ignis Jun 01 '11 at 18:30
  • @ignis: Yes, I know. I was implying that *all three* have virtually nothing in common. :) My apologies if that didn't come across effectively. – C. A. McCann Jun 01 '11 at 18:50
  • 1
    @camccann: In what way do C++ and Java constructors have "virtually nothing in common"? – Oliver Charlesworth Jun 01 '11 at 19:24
  • @Oli Charlesworth: Have you ever seen C++ written by someone who only knows Java? – C. A. McCann Jun 01 '11 at 19:27
  • 1
    @cammcann: No, but I can imagine! Either way, C++ and Java constructors are broadly the same concept, and have broadly similar semantics and syntax. Though I appreciate that some of the details are different. – Oliver Charlesworth Jun 01 '11 at 19:30
  • @Oli Charlesworth: The commonality is broad and superficial; the conceptual differences, rooted in how inheritance and memory management (among other things) are handled in each language, are subtle but critical. Thus exaggerating the differences is, from a high-level perspective, less misleading. :) – C. A. McCann Jun 01 '11 at 19:37
  • @cammccann: Fair enough! IMHO, the commonality is more than superficial, because issues such as memory management apply to the language as a whole. I'd go so far as to say that the *differences* are superficial (but important, nevertheless)... – Oliver Charlesworth Jun 01 '11 at 19:44
  • @Oli Charlesworth: Whereas I tend to see such core concepts as being inextricable from the nature of the language as a whole, which probably goes a long way to explaining the difference in perspective. Alas, my C++ is far too rusty to explore the matter in greater depth... – C. A. McCann Jun 01 '11 at 19:50
  • Well, it's not necessarily an *exact* duplicate, but this topic was discussed long ago as [Constructor in C](http://stackoverflow.com/q/537244/2509). – dmckee --- ex-moderator kitten Jun 02 '11 at 00:43

2 Answers2

17

C has no language support for objected-oriented concepts such as constructors.

You could manually implement this, along the lines of:

typedef struct
{
    int field1;
    int field2;
} MyObject;

MyObject *MyObject_new(int field1, int field2)
{
    MyObject *p = malloc(sizeof(*p));
    if (p != NULL)
    {
        // "Initialise" fields
        p->field1 = field1;
        p->field2 = field2;
    }
    return p;
}

void MyObject_delete(MyObject *p)
{
    // Free other resources here too
    if (p != NULL)
    {
        free(p);
    }
}

void MyObject_doSomethingInteresting(const MyObject *p)
{
    printf("How interesting: %d\n", p->field1 * p->field2);
}

If you want to get really advanced, you can use hideously-complex macros and function pointers to emulate polymorphism and all sorts (at the expense of type-safety); see this book.

See also this question.

See also this FAQ answer if you're interested in compiling object-oriented C++ into C.

Community
  • 1
  • 1
Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • 1
    Constructors aren't an OO concept. They're a programming language concept. E.g. [ML has had constructors](http://books.google.com/books?id=e0PhKfbj-p8C&q=constructor#v=snippet&q=constructor&f=false) since the 70s (aka "introduction forms"). – Don Stewart Jun 01 '11 at 18:08
  • 1
    @Don Stewart: I'm pretty sure these are two entirely different concepts that happen to use the same word, actually. The concept typically found in OO languages is closer to a formalized version of what the Haskell wiki calls "smart constructors". Might as well ask how to define ML/Haskell-style "functors"... – C. A. McCann Jun 01 '11 at 18:17
  • 1
    I disagree, @camccann, constructors in FP or OO *are* the same concept - they're *functions for building data types* (or objects, or classes). It just so happens that in Haskell you get constructors for free, so we call user-provided ones "smart constructors", but the same is true for some OO languages. – Don Stewart Jun 01 '11 at 18:21
  • 1
    @Don Stewart: The introduction of a new primitive value along with a 1:1 mapping to a corresponding elimination for it seems far more essential to the ML-style concept (as suggested by the phrase "introduction form" above) than the ability to use those forms as functions--I can easily imagine removing the latter from Haskell (in favor of some special pattern-building syntax, inverse of pattern matching) without changing the fundamental character of the language. These tiny comment boxes are not a very effective way to discuss the matter, though. – C. A. McCann Jun 01 '11 at 18:35
  • 2
    @Don, @cammcann: I know nothing of ML/Haskell; I was responding to the "C++" part of the question! In that context at least, they're definitely an OO concept. – Oliver Charlesworth Jun 01 '11 at 19:26
5

I suspect that @Oli Charlesworth's answer is what you really wanted here, but for completeness' sake, if you really want Haskell-style constructors:

  • Nullary data constructors like True and False can be represented easily by regular enum types. To stay accurate to Haskell you'll want to pretend that you can't treat them as integer values, unless you're also pretending that your Haskell type is an instance of Enum.

  • Data constructors for product types like (True, "abc") can be represented by functions that take appropriate arguments and return an appropriate struct. Haskell's "record syntax" can be imitated using a struct because C-style structs are already being imitated by Haskell's record syntax. Yay, recursion!

  • Data constructors for sum types like Nothing and Just 5 can be imitated by a union. To stay accurate to Haskell you'll need to "tag" the union to distinguish the cases safely, such as using a struct and an enum. Think of the | in Haskell's data declarations as indicating an untagged union, with the individual constructors like Nothing and Just being nullary constructors required to be the first element of a product type forming each branch. This is slightly more complicated to implement than you'd think after realizing that it's simpler than it sounds at first.

  • Type constructors don't really translate well to C. You might be able to fake it badly, if you want to, using macros and such. But you probably don't want to, so stick to monomorphic code.

If you want to put any of the above into practice in actual code, well... good luck and godspeed.

C. A. McCann
  • 76,893
  • 19
  • 209
  • 302