#define interface class
(here is more - http://www.codeproject.com/KB/cpp/CppInterfaces.aspx )
Does that make sense? Does this clarify the difference between interfaces and implementing them classes? Or it's confusing, because it's obvious that pure virtual classes are interfaces?
Do you use it? or "macros are evil"?
I'd say it makes no sense. The "solution" proposed in that article looks like a horrible mess - what's wrong with using C++ as it is? Why introduce some crappy macros when you can just define a pure abstract class when you need one and be done with it?
It looks like someone with C#/Java background was trying to find his way in C++ and got lost. It would only introduce bugs and confusion when encountered by developers actually familiar with C++.
A macro such as this is evil, because it hides the true language behind a facade that is not easily discerned if you don't know the secret.
A better way of defining interfaces is to use a common convention such as naming them with an "I" as the first character.
I really don't suggest to use these tricks, I consider smartass. Macros are not evil, but if someone includes your code and uses interface as a variable name (why not?), why does he/she have to spend 1 hour debugging with gcc -E because someone decided "interface" (which is not C++) would be smarter?
I dislike that.
C++ practitioners have come up with useful idiomatic ways of doing things. These idioms become part of the general, common dialect that other practitioners understand and easily work with.
The C++ programmer you hire off the street will know that a base class with all pure virtual methods and no implementation is an interface. They will know that public inheritance from it means its implementing that interface. They won't know the crazy macro language specified in that article.
I'd also add that idioms are especially important in C++ due to the ability to really shoot your foot off if you're not careful. In fact the generally used idioms in C++ may be C++'s most powerful feature.
I would never redefine or replace an existing keyword - it only leads to confusion by everyone but the author...
It is bad. I wouldn't use it, ever.
Conventionally: Defines in C/C++ are typically all in capital letters to make it obvious to any reader that it is a define, and to avoid name-clashes with function or variable names.
Practically: It is a very common name "interface" and this use of it will be dangerous just on that basis. But, of course, you could make the name more distinct, e.g., MY_PLATFORM_INTERFACE or something like that.
Philosophically: This is clearly a lame attempt at turning C++ into a more purist OOP language like Java or C#, and trying to somehow make the C++ syntax more familiar to newcomers from the Java/C# world. A programming language is what it is. If you want deep changes to be made, appeal to the standard committee, and be prepared to provide strong evidence. I think that such a small change to the syntax is ridiculous. I don't think anyone would not be able to switch to C++ because he can't get used to the idea that the interface keyword doesn't exist in C++.
Idiomatically: When you program in C++, you should expect C++ programmers to look at or review your code. If you introduce a thing like that that could look like an obscure compiler-specific extension of C++, you might throw a real C++ programmer off and he might spend his precious time wondering what compiler or extension is used that enables this "interface" keyword. Stick to C++ idiomatic syntax whenever possible. Otherwise, you will have to comment, next to every use of "interface", that this keyword is just a define for "class", in which case, you might as well just comment on the class declaration that this class is an interface and just use the "class" keyword as you normally would.
I don't get the point of doing this. How does it help make the code more readable to developers? Or even avoiding making it more obscure?
Better to use a class naming convention such as IClassName, that should be clear without obfuscating the code from developers working on it.
Instead of
#define interface class
Consider using the Visual C++ keyword __interface instead, and write your #define like this:
#ifndef _MSC_VER
#define __interface class
#endif
Also prefix your interface classes with the conventional "I" for additional clarity as #jonathan-wood suggested.
Using this approach, you get true compiler support for the interface pattern under Visual Studio, and everything still compiles happily cross-platform. Because of the double underscore, you also avoid the potential problem of symbol naming collision mentioned by #gd1.
Related
Coming from a good foundation in java to c++, I'm really confused on why when we use the cmath library we don't have to call it like: classname.function like we do in java (ex: Math.sqrt()). I saw that we can just call sqrt(). How does it know which class this method is coming from. I also wasn't able to see wether this function is static or not or any visibility type on cppreference.com so it did not help to give me a clue either.
It doesn't come from a class. Not every function in C++ is a class method. In fact, most of them aren't. Functions in C++ (and in many languages; Java is really the oddball here) can be standalone and can simply be called as-is.
Likewise, top-level functions can't be "static" in the Java sense, since they don't belong to a class. static is a keyword in C++, and inside a class it's similar to Java's definition, but you won't find yourself using it very often in C++. Outside a class, "static" means something totally unrelated.
The headline here is: Forget most of what you know about Java. Low-level control flow, like loops and conditionals, will mostly carry over. But C++ classes are a different beast, memory management in C++ is entirely different, and the way you structure your program is different.
Java paradigms work in Java, but if you follow those paradigms in C++, you'll make everything a (raw) pointer, stick everything inside of a class, and litter new calls throughout your program. I've seen code that's written like this. I've had professors who were obviously Java coders forced to teach C++, and it shows. Learn C++ as its own language, not as "diet Java". I cannot stress that point enough.
In C++ you may opt to use namespace to achieve exactly that. For example you may declare function doSomething within namespace Math and then you refer to that function as Math::doSomething.
Is there a way to find out what the protection level of a member is?
I'm making a singleton base-class and I'd like to ensure that the child class declares its constructor/destructor as private/protected. How can I do this?
template<class c>
class singleton
{
static_assert(std::is_private<&c::c> // does this exist?
|| std::is_protected<&c::c>);
static_assert(std::is_private<&c::~c>
|| std::is_protected<&c::~c>);
};
There is a paper written that proposed this in 2018, (and later 2019). In fact, it appears it was circulated in June of 2019 as part of the Committee's proposal process. However, I'm not really sure what happened to it (other then I think I found another revision).
Some compilers might support it experimentally. If they did, I believe the header you would use is <experimental/reflect> (according to the paper, at least).
Otherwise, you're kind of stuck. It appears reflection was deferred to a later standard, so nothing like this really exists in C++ as it stands. Hopefully it will make it into C++23. But for now we have to wait.
Unfortunately, what you are trying to do is not possible. So far, C++ doesn't have reflection features that are powerful enough.
In reality, programmers use singleton classes without needing protection mechanisms like this, because C++ is not designed for maximum compile-time validation. There are a whole lot of other similar things you can't do in C++ — in other words, it is impossible for C++ to accommodate for every possible feature users may expect, especially those that are not generally considered useful. Reflection is proposed because many people find it helpful, but so far the equivalent capabilities have not been included in C++.
One day I decided to start writing a video game in plain old C.
It was a lot of fun, and three months later (I sometimes have little time away from the job) I found myself in the need of some physics engine.
I decided to use Bullet physics engine, because it seems like one of the better ones out there for what I need.
Then, I found out Bullet doesn't really have a C API but only a full C++ API. Its C API is not maintained.
After a day of cursing, I 'converted' my project into C++, which is a bold statement for saying I typecasted all heap allocation and I use new and delete instead of malloc and free, and wrapped up some definitions in 'extern "C" { ... }'.
Some people would probably shoot me for doing that, but I saw no other option to using a performance-tasking thing such as this physics engine, which only has a C++ API, in C.
So now, I'm compiling with g++, while still writing mostly "C" code.
I find myself a little less happy, because the code no longer feels as pure.
C++ gives me some strange error messages, while I have nothing against the language I often do not like the g++ parser.
Aside from the fact that I can now happily bounce objects into each other, some of the smallness and purity of my pet project has been deserted now.
I'm wondering if I did the right thing. Can I ask for some advice, should I just carry on and not worry about using a C++ compiler for my 'mostly' C code? Are there other ways to use this API in C without any performance hits or overdone maintenance work?
I'm wondering if I did the right
thing.
Well, you needed a component for your project, and instead of inventing it again from scratch, you reused an existing piece of software. It actually sounds right to me.
Can I ask for some advice, should I
just carry on and not worry about
using a C++ compiler for my 'mostly' C
code?
You don't need to worry at all. C++ is almost 100% C compatible. There are no penalties on doing that. You have actually earned better compile-time checkings due to a much stricter type system.
Are there other ways to use this API
in C without any performance hits or
overdone maintenance work?
No, you can't use the API in C without converting your code to C++. C++ identifiers are mangled: this means that, even if you were ready to use the C++ API from plain C, you wouldn't know how to refer to them. Theoretically this is possible, in practice it isn't.
Your way is the correct one.
Good luck with that game!
I think you're overly concerning yourself with things that aren't really problems. You say that some of the purity has gone. Well, I can understand this. You wrote it in C and then, realizing you had to use C++ to use an API of choice, shoehorned it in. Now it doesn't feel like your pet baby anymore. This is a subconscious issue, not a programming one.
I suggest you bite the bullet (haha), and rewrite your project in C++. Then it will be pure again, you'll learn a lot on the way, and won't feel like your C-child is being sodomized.
Depending on how tightly coupled the different subsystems of your engine are, it might be feasible to write different parts of the engine in different languages.
For example, you could factor out the physics part into a C++ module which exports a C API and let the rest of your application stay in C. However, it might make more sense to write the central part of the system in C++ and refactor your existing C code into seperate modules.
If you want to write your project in C, write it in C and make a C wrapper for the library; have a look at this question for some advice about it.
Otherwise, rewrite your project in C++; but please, don't write yet another C project with some C++ here and there, in my experience these projects can quickly become a mess (and if you write code with a C mindset but calling C++ code weird things start to happen when exceptions are added to the mix).
Don't worry about writing mostly C code and compiling it with C++. Just adopt using new/delete instead of malloc/free and you'll be fine. The advantage of using new is that you don't have to cast the result to the proper pointer type (implicit casts from void* to other pointers are disallowed in C++) and that new will never return an invalid pointer. You loose realloc() though. (And no, don't even think of mixing new/delete with realloc :))
The only reasons you would keep a project as "pure C" are either because of source code compatibility, tool support, or because of language standards (MISRA-C etc). "I want it to feel pure" is probably not a very rational argument.
If keeping the code as pure C for such reasons is important, your could have written a "wrapper" DLL (assuming Windows) in C++, which does all the communication with your 3rd party API. You'd get a fair bit of overhead of course.
The strange error messages are no doubt caused by the stricter typing in C++, which can be a bless or a curse depending on the situation. A C++ compiler will be more likely to slap your fingers when encountering dangerous implicit typecasts (integer promotions etc) and it will likely enforce stricter "const correctness". But at the same time, it will moan about void pointers, which are considered good generic programming in C, but dangerous, sloppy and possibly redundant in C++.
One option is to convert the C++ code to C using LLVM. See this FAQ from the project's website: Can I convert C++ code to C code?
The MFC has all class names that start with C. For example, CFile and CGdiObject. Has anyone seen it used elsewhere? Is there an official naming convention guide from Microsoft that recommends this style? Did the idea originate with MFC or was it some other project?
It's evil. Don't use Hungarian Notation for anything but abstracted things.
For instance, btnSubmit is ok to describe a button named Submit(which would have an accompanying lblSubmit for the label next to the button)
But things like CMyClass for Class and uiCount for unsigned integer named count does not help programmers and just leads to extra wasteful typing.
Something a bit similar is used in Symbian C++, where the convention is that:
T classes are "values", for example TChar, TInt32, TDes
R classes are handles to kernel (or other) resources, for example RFile, RSocket
M classes are mixins, which includes interfaces (construed as mixins with no function implementations). The guideline is that multiple inheritance should involve at most 1 non-M class.
C classes are pretty much everything else, and derive from CBase, which has some stuff in it to help with resource-handling.
HBufC exists primarily to generate confused posts on Symbian forums, and having its very own prefix is just the start. The H stands for "huh?", or possibly "Haw, haw! You have no STL!" ;-)
This is close in spirit to Apps Hungarian Notation rather than Systems Hungarian notation. The prefix tells you something about the class which you could look up in the documentation, but which you would not know otherwise. The whole point of naming anything in programming is to provide such hints and reminders, otherwise you'd just call your classes "Class001", "Class002", etc.
Systems Hungarian just tells you the type of a variable, which IMO is nothing to get very excited about, especially in a language like C++ where types tend to be either repeated constantly or else completely hidden by template parameters. Its analogue when naming types is the Java practice of naming all interfaces with I. Again, I don't get very excited about this (and neither do the standard Java libraries), but if you're going to define an interface for every class, in addition to the interfaces which are actually used for polymorphism in non-test situations, then you need some way to distinguish the two.
That was a old C++ coding style, and MFC was probably one of the last things to use it.
It was usually just a convention of C++ (and maybe a few other languages), and hence it started falling out of favor as the languages became more interoperable, through COM and then .NET.
You still see it's cousin, the "I" prefix for interfaces, pretty often. I've always found it interesting that "I" survived when "C" died, but that was probably because interfaces were used so heavily in COM interoperability.
I remember Borland compilers were comming with libraries where class names started with 'T'. Probably for "type" :)
I can't answer all your questions, but as far as I know, it's just to distinguish the MFC classes from other classes -- a form of Hungarian Notation.
Interestingly, it's apparently controversial not just outside MS, but inside as well.
Years ago naming convention is crucial to help identifying the class, type of even the grouping of the class. Dont forget back then there was no namespace and no/limited intellisense available. C is a form of Hungarian notation but certainly made popular by MFC. Borland and Delphi was using T - as prefix for Type
While MFC and lots of software written for Windows used the "C" convention for classes, you generally don't find the latter in software written for UNIX platforms. I think it was a habit very strongly encouraged by Visual C++. I remember that Visual C++ 6.0 would prefix a "C" to any classes that one created with the class wizard.
See here : http://www.jelovic.com/articles/stupid_naming.htm for a long article on this issue.
Such conventions for variables are useful for languages like Fortran where you don't need to declare the types of your variables before using them. I seem to recall that variables who's names started with "i" or "j" defaulted to integers, and variables who's names started with "r" and other letters defaulted to real (float) values.
That people use similar for languages where you do need to declare variables - or for class definitions - is probably just a relic of someone misunderstanding the old code conventions from languages like Fortran where it actually mattered.
When writing applications that use the Qt libraries, we use a naming convention that distinguishes classes that are directly or indirectly derived from QObject from classes that aren't. This is useful because you can tell from the class name whether or not it supports signals/slots, properties, and all the other goodies that come from QObject.
we use it at work, like many other naming conventions
by many I meant C for classes, p for pointer, m_ for members, s_ for static members, n for integer ... not many documents
personally I find that hungarian notation helps me, in that I can look at a screen full of variables and instantly know what they are as I try and absorb the logic. Your only argument against it I see is "extra typing"
I think I have an advanced knowledge of C++, and I'd like to learn C.
There are a lot of resources to help people going from C to C++, but I've not found anything useful to do the opposite of that.
Specifically:
Are there widely used general purpose libraries every C programmer should know about (like boost for C++) ?
What are the most important C idioms (like RAII for C++) ?
Should I learn C99 and use it, or stick to C89 ?
Any pitfalls/traps for a C++ developer ?
Anything else useful to know ?
There's a lot here already, so maybe this is just a minor addition but here's what I find to be the biggest differences.
Library:
I put this first, because this in my opinion this is the biggest difference in practice. The C standard library is very(!) sparse. It offers a bare minimum of services. For everything else you have to roll your own or find a library to use (and many people do). You have file I/O and some very basic string functions and math. For everything else you have to roll your own or find a library to use. I find I miss extended containers (especially maps) heavily when moving from C++ to C, but there are a lot of other ones.
Idioms:
Both languages have manual memory (resource) management, but C++ gives you some tools to hide the need. In C you will find yourself tracking resources by hand much more often, and you have to get used to that. Particular examples are arrays and strings (C++ vector and string save you a lot of work), smart pointers (you can't really do "smart pointers" as such in C. You can do reference counting, but you have to up and down the reference counts yourself, which is very error prone -- the reason smart pointers were added to C++ in the first place), and the lack of RAII generally which you will notice everywhere if you are used to the modern style of C++ programming.
You have to be explicit about construction and destruction. You can argue about the merits of flaws of this, but there's a lot more explicit code as a result.
Error handling. C++ exceptions can be tricky to get right so not everyone uses them, but if you do use them you will find you have to pay a lot of attention to how you do error notification. Needing to check for return values on all important calls (some would argue all calls) takes a lot of discipline and a lot of C code out there doesn't do it.
Strings (and arrays in general) don't carry their sizes around. You have to pass a lot of extra parameters in C to deal with this.
Without namespaces you have to manage your global namespace carefully.
There's no explicit tying of functions to types as there is with class in C++. You have to maintain a convention of prefixing everything you want associated with a type.
You will see a lot more macros. Macros are used in C in many places where C++ has language features to do the same, especially symbolic constants (C has enum but lots of older code uses #define instead), and for generics (where C++ uses templates).
Advice:
Consider finding an extended library for general use. Take a look at GLib or APR.
Even if you don't want a full library consider finding a map / dictionary / hashtable for general use. Also consider bundling up a bare bones "string" type that contains a size.
Get used to putting module or "class" prefixes on all public names. This is a little tedious but it will save you a lot of headaches.
Make heavy use of forward declaration to make types opaque. Where in C++ you might have private data in a header and rely on private is preventing access, in C you want to push implementation details into the source files as much as possible. (You actually want to do this in C++ too in my opinion, but C makes it easier, so more people do it.)
C++ reveals the implementation in the header, even though it technically hides it from access outside the class.
// C.hh
class C
{
public:
void method1();
int method2();
private:
int value1;
char * value2;
};
C pushes the 'class' definition into the source file. The header is all forward declarations.
// C.h
typedef struct C C; // forward declaration
void c_method1(C *);
int c_method2(C *);
// C.c
struct C
{
int value1;
char * value2;
};
Glib is a good starting point for modern C and gets you used to concepts like opaque types and semi-object orientation, which are common stylistically in modern C. On the other end of the spectrum standard POSIX APIs are kind of "classical" C.
The biggest gap in going from C++ to C isn't syntax, it's idiom and there, like C++, there are different schools of programming. You'll write fairly different C if you doing a device driver vs., say, an XML parser.
Q5. Anything else useful to know?
Buy a copy of K&R2 and read it through. On a cost per page basis it'll probably be the most expensive book on computing you'll ever buy with your own money but it will give you a deep appreciation for C and the thought processes that went into it. Doing the exercises will also hone your skills and get you used to what is available in the language as opposed to C++.
Taking your questions in order:
Unfortunately, there's nothing like Boost for C.
Nothing that's really on the order of RAII either.
The only compiler that tries to implement C99 is Comeau.
Lots of them all over the place, I'm afraid.
Quite a bit. C takes quite a different mindset than C.
Some of those may seem rather terse, but such is life. There are some good libraries for C, but no one place like Boost that they've been collected together or given a relatively uniform interface like Boost has done for C++.
There are lots of idioms, but many of them are in how you edit your code, such as sort of imitating RAII by writing an fopen() and a matching fclose() in quick succession, and only afterwards writing the code in between to process the data.
The pitfalls/traps that wait around every corner mostly stem from lack of dynamic data structures like string and vector, so you frequently have to write such things yourself. Without operator overloading, constructors, etc., it's considerably more difficult to make them really general purpose. Lots of libraries have them, but you end up rolling your own anyway because:the library doesn't do quite what you want, orusing the library is more work than it's worth.
The difference in mindset is almost certainly the biggest thing, at least for me. When I'm writing C++, I concentrate almost all my real effort on designing the cleanest possible interfaces, and I tend to treat the implementation of an interface as almost throwaway code. For the most part, I don't plan on making minor tweaks to that part of the code -- as long as the interface is good, replacing the entire implementation is usually easy enough that I don't worry about it much.
In C, it seems (at least to me) much more difficult to separate the interface from the implementation nearly as thoroughly or cleanly. As such, I tend to spend a lot more time trying to implement every part of the code as cleanly as possible, because later changes tend to be more difficult and throwing away and replacing pieces that aren't very good is substantially less likely to work out very well.
Edit (since people have raised questions about C99 support): While my statement about lack of C99 support may seem harsh, the fact is that it's true.
MS VC++: supports C95, and has a couple C99 features (e.g. C++ style comment delimiters), mostly because C99 standardized what they'd previously had as an extension.
Gnu: According to C99 Features Status page, the most recent iteration of gcc (4.4) has some C99 features, but some (including VLAs) are characterized as "broken", and others as "missing". Some of the missing "features" are really whole areas, not individual features.
PCC: The PCC site claims C99 conformance only as a goal for the future, not as a present reality.
Embarcadero Technologies (nee Borland) don't seem to say anything about conformance with C99 at all -- from the looks of things, the last time they worked on the C compiler may well have been before C99 was even released.
Microsoft openly states that they have no current plans for supporting C99, and they're not going to even consider it until VS 2010 is released. Though I can't find any public statements about it, Embarcadero appears about the same: no hint of a current plan, and nor even that they're going to consider working on it anytime soon.
While gcc and pcc both seem to have plans, they're currently just that: plans. They both openly admit that at the present time, they aren't really even very close to conforming with C99.
Here's a quick reference of some of the major things you'll want to know.
This is advice you didn't ask for: I think most potential employers take it as a given that if you C++ you know C. Learning the finer points of C, while an interesting academic exercise, will IMO not earn you a lot of eligibility points.
If you ever end up in a position of needing to do C, you'll catch on to the differences quickly enough.
But don't listen to me. I was too lazy and stupid to learn C++ :)
Anything else useful to know ?
C99 is not subset of c++ any revision, but separate language.
Just about the biggest shock I had when I went back to C was that variables are defined at the function level - i.e. you can't scope variables inside a block(if statement or for loop) inside a function.
Except for very few cases, any C code is valid C++, so there isn't actually anything new you should learn.
It's more a matter of unlearning.
Not using new, not using classes, defining variables at the beginning of a code block, etc.
In a strict sense, C++ is not object-oriented, but it's still procedural with support for classes. That said, you are actually using procedural programming in C++ already, the most shocking change will be not having classes, inheritance, polymorphism, etc.
As C++ is almost a superset of C89, you should know just about all of C89 already. You probably want to concentrate on the differences between C89 and C99.