Page 2 of 2
Re: C++ classes, inheritance and portability
Posted: Tue Feb 22, 2011 9:57 am
by FlashBurn
XenOS wrote:
but the question is, if one uses C style coding anyway, why not use C from the beginning instead of C++?
And this says if you want to code in C++ you always have to use oo-style or go back to C! I use oo where it is better and easier and use C-style where it is faster and easier.
Re: C++ classes, inheritance and portability
Posted: Tue Feb 22, 2011 10:52 am
by xenos
That's exactly the reason why I prefer using C++ in my kernel and device drivers. IMHO, C++ classes and objects provide a very good abstraction of devices such as serial / parallel / USB ports, drives, CPUs, and processing objects such as processes, threads, messages...
Re: C++ classes, inheritance and portability
Posted: Tue Feb 22, 2011 11:16 am
by rdos
One can create horrible, non-OO oriented code in C++, and OO code in assembly. It is not the language used that defines if code is object oriented or not, it is how the code is designed and implemented. I use an OO approach in my (currently) assembly-only kernel, and one day I will provide a real C++ interface to system components in the kernel, and write some more complex drivers in C++.
One thing that doesn't map well to C++ is the (prefered) use of handles instead of pointers in typical OS interfaces. Handles provides a much stronger validation of objects than using only pointers. When it comes to userlevel interfaces, the direct use of pointers is very bad.
Re: C++ classes, inheritance and portability
Posted: Tue Feb 22, 2011 1:11 pm
by rdos
berkus wrote:We heard that from Linus already. C++ provides excellent support for handles, sometimes you don't even know it's a handle and just think it's a pointer. Think about it.
Can you give an example about this "excellent support for handles", and how it can validate handles without any external support? I don't count various aliasing of addresses into handles, as this is not safe. Seriously, I'm interested in how to solve this issue myself.
Re: C++ classes, inheritance and portability
Posted: Tue Feb 22, 2011 1:40 pm
by xenos
Of course one can also use OO in assembly code and non-OO in C++. But in my opinion it is much simpler in C++ as it provides classes, templates, inheritance and so on, which make it much easier to implement an OO design. Of course, if you use an assembler which supports such basic OO elements (or at least supports macros such that one can write an own implementation of such elements), implementing an OO design in assembler is just as easy as in C++.
Re: C++ classes, inheritance and portability
Posted: Wed Feb 23, 2011 4:07 am
by Solar
XenOS wrote:...the object oriented nature of C++...
Chiming in on this:
C++ is,
by design, a multi-paradigm language. Reducing it to its OO subset is not doing the language justice (and not effective, either).
The book "The C++ Programming Language" by Stroustrup begins with a quote by Benjamin Lee Whorf: "Language shapes the way we think, and determines what we can think about". This is not by accident, as this quote is very fitting with regards to C++. Don't get caught in some "paradigm" strait jacket.
Re: C++ classes, inheritance and portability
Posted: Wed Feb 23, 2011 3:59 pm
by rdos
Uhm, I never work with written specifications when I write OS-code. I keep all the details in my head.
But, I can give you some basics.
I already have som handle-functions that looks like this in C:
Code: Select all
// base type for handles
struct THandleBase
{
int type_id;
int handle;
};
// register handle, and auto-deletion when a process terminates
void RegisterHandle(int type_id, void (*delete(THandleBase *ptr)));
// basic functions
THandleBase *AllocateHandle(int size, int type_id);
void FreeHandle(THandleBase *ptr);
THandleBase *DerefHandle(int handle);
These should somehow be encapsulated into C++ classes.
Re: C++ classes, inheritance and portability
Posted: Thu Feb 24, 2011 2:59 am
by xenos
Solar wrote:C++ is, by design, a multi-paradigm language. Reducing it to its OO subset is not doing the language justice (and not effective, either).
Of course, C++ has many other nice features besides OO, things like template functions, overloading, namespaces and so on, and one can do very nice things in C++ without even touching OO.
I just wanted to mention that if one doesn't use any of these features, or uses them only to mimic the behavior of C, one might get along easier using C from the beginning.
Re: C++ classes, inheritance and portability
Posted: Thu Feb 24, 2011 7:05 am
by Solar
I was aiming at the original comment that XenOS didn't want to use that "namespace approach" because to him "it mainly circumvents the object oriented nature of C++".
I wanted to point out that C++ is, first and foremost, a pragmatic language. Use whatever floats your boat. Don't worry about whether it's "properly OO" or not. "Clean design", in C++, means "readable" and "maintainable", not "pure".
(It's something I came to respect, and to a certain extend, love, in C++ and Perl. I cringe every time I have to write up a Java class only to put a 'static void main' in there. Of course, it has been abused as a lame excuse for shoddy design, giving both languages a bad rep...)
Re: C++ classes, inheritance and portability
Posted: Thu Feb 24, 2011 7:34 am
by xenos
@berkus: Of course one can write plain C code in C++, that's just what I said, and it's not breaking any C++ rules. But that can also be done in C, without dealing with things like name mangling and so on. So it appears to me that writing plain C code without any of the C++ features (and maybe mixing it with assembly) in C is simpler than doing the same in C++.
@Solar: Thanks for clarification. The reason why I tried to stick to the OO paradigm is not that I'm using C++, but it's rather the other way round: I use C++ in my kernel because my aim is to implement an OO design. Some parts of my kernel, such as the task scheduler or the memory manager, encapsulate certain functionalities and operate on a set of private data, so my first idea was to model them as instances of C++ classes. But after some time of thinking and writing simple examples for the different designs it seems that using namespaces for such "one-instance-only objects" (I don't want to use the word singleton here) fits my needs better than the other approaches. I guess I will use C++ classes / objects only if I actually need more than one instance of something, such as address spaces, I/O APICs, CPUs, buses or whatever.
Re: C++ classes, inheritance and portability
Posted: Thu Feb 24, 2011 7:36 am
by rdos
OK, I should have outlined how the handle basics works. The handle numbers are per process, and uses a single number series for all devices that use handles. In the current implementation they are 16-bits. There is no relationship between a handle number and the object it encapsulates. The handle module has an array that links handle numbers to a memory pointer and a memory pool.
A handle using module will first identify it's ID, and a delete function to close open handles when a process terminates without closing all of its handles. This should be a static method (probably).
Next, it will allocate handles.
Code: Select all
THandleBase *AllocateHandle(int size, int type_id);
void FreeHandle(THandleBase *ptr);
Allocate handle takes a size for the object to be encapsulated, and the previously defined ID (which the class should keep as an global). It then gets a pointer to a memory block that first contains the mandatory fields (ID and handle number), and some space for itself (as indicated by size). Usually, drivers
will put a selector / memory address here. In this case it could be a pointer to the current object to be encapsulated (this pointer). IOW, the size parameter
will always be 12, and the returned type will look something like this:
Code: Select all
struct THandle
{
int type_id;
int handle;
void *object;
};
I think that allocate handle should be in the constructor and free handle should be in the desctructor of the basic handle-class. This class will also
contain something that will dereferences handles:
Code: Select all
class THandleObject
{
protected:
THandleObject(int ID);
~THandleObject();
static THandleObject *Deref(int Handle, int ID);
int Handle;
public:
int GetHandle() {return Handle};
};
THandleObject::THandleObject(int ID)
{
THandle *handleobj = AllocateHandle(sizeof(THandle), ID);
Handle = handleobj->handle;
handleobj->object = this;
}
THandleObject::~THandleObject();
{
THandle *handleobj = DerefHandle(handle);
FreeHandle(handleobj);
}
THandleObject *THandleObject::Deref(int Handle)
{
THandle *handleobj = DerefHandle(handle);
if (handleobj)
return handleobj->object;
else
return 0;
}
classs TSomeHandleObject : public THandleObject
{
TSomeHandleObject();
static void DoSomeFunction(int Handle, void *Buf);
}
TSomeHandleObject::TSomeHandleObject()
: THandleObject(ID)
{
}
TSomeHandleObject::DoSomeFunction(int Handle, void *Buf)
{
TSomeHandleObject *obj = (TSomeHandleObject *)Deref(Handle, ID);
// do something
}
The problem I can see here is that all methods end up as static, which seems to defeat the idea of OO.
Re: C++ classes, inheritance and portability
Posted: Thu Feb 24, 2011 2:47 pm
by xenos
berkus wrote:It really isn't. C++ is more strict about declarations and preserves a lot more type information, so it's a lot harder to shoot yourself in the foot than with plain C.
Yes, that's IMHO one of the "features" of C++. If you make use of C++'s stricter typing, you already left the "pure C" world and stepped right into the world of C++ programming.