Is C++ dead?

Pages: 12345
<super late reply>

chrisname wrote:

I don't know why, I just prefer C. I don't like OOP. You might say "You don't have to use OOP," but then, I'd just be using C with a C++ compiler.

For some types of programs, I'd agree that C++ is better. Games, for example... I can see how OOP is useful for games; but it's not for me.


This is a little silly. People that "don't like OOP" just don't understand it.

The standard C library is full of OOP. You use it and enjoy it without realizing it.

Take stdio.h's FILE for example. Do you know what any of its members are? Can you access them directly? Of course not. They're all hidden from you to prevent you from mucking up the internal state of the object. Just like private variables.

Instead, you use FILEs with a series of "member functions" like fopen, fread, etc. How they work and what internal state changes they make don't matter. What matters is that they perform an abstract task on a provided object.

This is what OOP is about. Having an object which represents something specific.

It keeps code organized, functional, a lot more reliable, and a lot harder to screw up with simple mistakes.

Can you imagine what hell FILE would be if you had to change all if its members manually every time you wanted to do something? If you were responsible for all these little details and forgetting to do a step resulted in catastrophic failure?

OOP is everywhere in C. Not just in the standard library, but in pretty much any other library you can download and use.

C++ just changes the syntax a bit to make it easier to do.


Although granted, OOP is not the best approach in every situation. And mindlessly making member variables private just for the sake of making them private (as if it were some kind of "rule") is absurd.

I'd just be using C with a C++ compiler.


I'd argue you should do this anyway. But I think I mentioned that in another thread somewhere.

</super late reply>
Disch; you're right. But I still disagree with writing C with a C++ compiler. With gcc, that will lead to a larger executable because it links libstdc++ into the executable:
$ cat >hello.c
#include <stdio.h>

int main()
{
    printf("Hello, world!\n");
    return 0;
}

$ cat >hello.cpp
#include <cstdio>

int main()
{
    printf("Hello, world!\n");
    return 0;
}

$ gcc -o hello hello.c
$ g++ -o hello++ hello.cpp

$ ls -l hello
-rwxr-xr-x 1 chris users 6483 2010-03-01 19:52 hello

]$ ls -l hello++
-rwxr-xr-x 1 chris users 6870 2010-03-01 19:52 hello++


As you can see, even though the two programs have exactly identical code, the C++ program is larger (6483 bytes vs. 6870 bytes). It's not a big difference; but that's because of the size of those two programs. If they were big programs, the C++ executable would be much bigger.

So I don't think it's a good idea to write C with a C++ compiler; because then you would end up with bigger executables for no reason.

I have actually started writing C++ again. The main reason I wanted to was because I wanted to have a program which had a Curses UI and a Qt UI; but I didn't want to have to conditionally compile
1
2
3
4
5
#if defined CURSES_UI
    return curses_ui_init();
#elif defined QT_UI
    return qt_ui_init();
#endif 


so instead; I will have one .cpp and .h file which will contain all the preprocessor stuff, and a namespace ui; so I can just
return ui::init();
which is obviously a lot neater.
If they were big programs, the C++ executable would be much bigger.
Nope. Linking a library statically is a one time size penalty. The function is size+k, not size*k.
So I don't think it's a good idea to write C with a C++ compiler; because then you would end up with bigger executables for no reason.
http://www2.research.att.com/~bs/bs_faq.html#Hello-world
Nope. Linking a library statically is a one time size penalty. The function is size+k, not size*k.

Of course it is, my mistake.
Hey there, FILE*s are not an example of OOP in C. They are "structured programming".

True OOP requires polymorphism, without which you are just using object-based techniques.

While true OOP is entirely possible in C, the language does not support it and thus you would need to implement the proper infrastructure to use it (but that's what C++ does for you anyway).

Hope this helps.
So object-based techniques are not object-oriented programming?

*shrugs*

anyway, FILE* does seem to have a little faux polymorphism going on. You can fprintf to stdout, so stdout is a FILE* even though it's clearly a different type from FILE*s opened with fopen.

IIRC anyway. Or maybe I'm making that up. Is 'stdout' actually an identifier the way cout is?

I can't exactly test it right now... so yeah. I could very easily be wrong on that one.
I think stdout is a FILE *, as well, since you can fprintf() to it and to an actual file, and of course C doesn't have overloading.
No to Disch; Yes to helios, stdout is a FILE* just like any other. It might be a #defined alias though (it is in GCC and Dinkumware), or it might be a built-in object that the compiler defines (that is, which is not declared or defined in any header file)...

Object-based techniques have always existed. Just as you noted above, the C standard library is full of them.

However, an object oriented system is defined by having polymorphism. Otherwise it is only object-based.

http://en.wikipedia.org/wiki/Object-based
http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming

Hope this helps.
Last edited on
Right I know stdout is a FILE*, but it doesn't write to an actual file like fopen'd files do. It has a different purpose.

So internally it must be a different type, right?

FILE is the "abstract base class" so to speak. So yeah you can fprintf to stdout and to a file, but the end result is 2 clearly different things.

Can you fseek() stdout? or rewind() or ftell()? Those will all compile okay, of course, but will they have the same result as they would when performed on a fopen'd file?
The internal structure's function pointers just point to something different. That's it. It's not polymorphism or inheritance, it's just a type of dynamic binding.
Last edited on
The revolutionary concept that Unix provided was the concept of a stream.

There are various types of streams, including files, devices, sockets, etc. Different types of streams have different access characteristics, but they are still streams. Hence, things like:
% a.out > out.txt
work just fine.

In C, a stream is managed by either a low-level file descriptor (or on non-unix platforms, whatever it is that the underlying system uses to reference an open stream), or by a convient, high-level FILE* which does a lot of bookkeeping for you.

Inside the FILE structure is a list of function pointers that do the work of communicating with the opened file/device/port/whatever.

The standard streams are special in C -- but they are amazingly revolutionary also. Before C came along, just talking to the user typically required a lot of work to set up, and it was system-dependant and often required some fancy batch programming.
Right

So.... how is this not polymorphism?

You guys are pretty much describing exactly how you would go about faking polymorphism / virtual functions in C.
closed account (z05DSL3A)
Disch wrote:
So object-based techniques are not object-oriented programming?
Duoas wrote:
No to Disch; ... http://en.wikipedia.org/wiki/Object-based


The link says "A somehow limited version of object-oriented programming where one or more of the following restrictions applies:", so yes using object-based techniques is still object-oriented programming just without the full tool set.

I have seen this sort of discussion on many occasion and they never get it definitively resolved. It all revolves around peoples interpretation of the main phrases and the definitions they have for the same. For example, as I recall, I have never read a definition that says that Object Oriented Programming requires polymorphism, only that the programming techniques may include polymorphism, inheritance, etc. I'm not even sure that I could say where to find a definitive definition of object-oriented programming, as in being able to reference the definition, as I don't think there is a consensus as to what it is. Is it purely a way of thinking about the problem and solution, in terms of 'Objects' (attributes and behaviors encapsulating an entity), or is it all to do with program structuring?
Both inheritance and polymorphism are possible in C; the source of OpenMotif is an example of this. Sure, polymorphism is implemented with callbacks but isn't that exactly how C++ compilers do it, as well?
@Duoas,
% a.out > out.txt

Do you use a C shell? AFAIK Berkley csh used a % sign for a prompt...

Right I know stdout is a FILE*, but it doesn't write to an actual file like fopen'd files do. It has a different purpose.

So internally it must be a different type, right?


FILE* is just a struct (probably typedef struct file { ... } FILE; or similar). fopen, fread, fwrite, fclose and friends just operate on the members inside the struct. Then it uses syscalls or the system API to actually operate on the file. The UNIX FILE structure has an integer which stores the file's descriptor, and in fopen, you'd have this:

1
2
3
4
5
6
7
8
9
10
FILE* fopen(const char* path, const char* "w")
{
    FILE* f = (FILE*)malloc(sizeof(FILE));

    /* ... */
    f->fd = open(path, 0); /* Open the file, store it's descriptor in f->fd */
    /* ... */

    return f;
}


and in fclose, you'd have this:

1
2
3
4
5
6
7
8
void fclose(FILE* f)
{
    /* ... */

    close(f->fd);

    free(f);
}

(although I think I got the return type wrong. I can't remember off the top of my head what fclose returns)

It's all in K&R.
Last edited on
chrisname wrote:
FILE* is just a struct (probably typedef struct file { ... } FILE; or similar). fopen, fread, fwrite, fclose and friends just operate on the members inside the struct. Then it uses syscalls or the system API to actually operate on the file.


Yes yes. I know all this.

It's written in C, so of course it's only going to have C constructs. How it's implemented doesn't matter, it's what it does and how it's used that is what makes it OOP.

The point here is it represents an abstract concept and can do two (or more) entirely different things depending on the type of FILE you have.

Outputting to a console, and outputting to a file are two very different things. Yet FILE and friends let you do it with the exact same interface. This is like the exact definition of an abstract base class. Only C doesn't have abstract base classes as a language feature, so instead it implements it through a pointer to a black-box structure.


It doesn't matter if FILE's implementation doesn't have any function pointers.
It doesn't matter if FILE doesn't have any special cases for stdout

What matters is that at some point down the line, different code is going to be necessary to write to the console vs. write to the screen. I mean these are two clearly different tasks. There's no way they're accomplished exactly the same way.

Yet to the person using FILE, the differences are unnecessary to know because FILE treats it all the same way.

I don't why you guys don't see it. This just screams polymorhpism to me. Maybe I'm just crazy. =P


As for the whole UNIX file descriptor thing, I guess that would mean that FILE in that instance isn't polymorphic, but it takes advantage of the file descriptor's polymorphic behavior.
I wrote out a long reply, but my XServer decided to die. I can't be bothered to write out the reply again...

Outputting to a console, and outputting to a file are two very different things

in windows. In UNIX, outputting to a console is outputting to a file.
The file descriptors 0, 1 and 2 are created for every program and represent stdin, stdout and stderr respectively.
Hello world in UNIX:
1
2
3
4
5
6
7
8
#include <unistd.h>

int main()
{
    char* s = "Hello, world!\n";
    write(1, s, sizeof(s));
    return 0;
}


It's literally just writing to a file.

Also, if you open up any terminal, virtual terminal or terminal emulator and type "tty" it will tell you what tty (character block file) it's associated with.

Example:
1
2
$ tty
/dev/pts/1
in windows.
Not really.
1
2
3
4
5
6
7
#include <fstream>

int main(){
	std::ofstream file("CONOUT$");
	file <<"Hello, World!\n";
	return 0;
}
Oh, I didn't know that. I wondered how windows handled console IO.
Pages: 12345