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.XenOS wrote: but the question is, if one uses C style coding anyway, why not use C from the beginning instead of C++?
C++ classes, inheritance and portability
Re: C++ classes, inheritance and portability
- xenos
- Member
- Posts: 1119
- Joined: Thu Aug 11, 2005 11:00 pm
- Libera.chat IRC: xenos1984
- Location: Tartu, Estonia
- Contact:
Re: C++ classes, inheritance and portability
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
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.
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
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.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.
- xenos
- Member
- Posts: 1119
- Joined: Thu Aug 11, 2005 11:00 pm
- Libera.chat IRC: xenos1984
- Location: Tartu, Estonia
- Contact:
Re: C++ classes, inheritance and portability
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
Chiming in on this:XenOS wrote:...the object oriented nature of C++...
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.
Every good solution is obvious once you've found it.
Re: C++ classes, inheritance and portability
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:
These should somehow be encapsulated into C++ classes.
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);
- xenos
- Member
- Posts: 1119
- Joined: Thu Aug 11, 2005 11:00 pm
- Libera.chat IRC: xenos1984
- Location: Tartu, Estonia
- Contact:
Re: C++ classes, inheritance and portability
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.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).
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
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...)
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...)
Every good solution is obvious once you've found it.
- xenos
- Member
- Posts: 1119
- Joined: Thu Aug 11, 2005 11:00 pm
- Libera.chat IRC: xenos1984
- Location: Tartu, Estonia
- Contact:
Re: C++ classes, inheritance and portability
@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.
@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
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.
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:
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:
The problem I can see here is that all methods end up as static, which seems to defeat the idea of OO.
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);
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;
};
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
}
- xenos
- Member
- Posts: 1119
- Joined: Thu Aug 11, 2005 11:00 pm
- Libera.chat IRC: xenos1984
- Location: Tartu, Estonia
- Contact:
Re: C++ classes, inheritance and portability
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.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.