THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 26/02/2003 at 23:11, xxxxxxxx wrote:
You shouldn't be so fast to judge C++. It's complex, but only a mess the first few years of using it. Actually, Java could benefit from references, because currently one has to use cludges like "class Integer" to pass ints by reference/pointer.
The distinction between references and pointers is more semantic than technical (even if it's nice to know for a function that it will never receive a null pointer, and that a reference cannot change). As always there are several schools.
My interpretation of modern C++ is to use references where possible and pointers when you have to, due to the dangers of pointers that can be NULL and change.
In the C4D SDK there's a distinction between what I call C4D classes and SDK classes.
The former are things like BaseObject that are only reflections of a real object in C4D space, or as Platon would have said it shadows of an idea in C4D. These are characterised by having an ::Alloc() function for instantiation. When these objects are passed they are usually passed as pointers.
The latter are things like String, more self contained objects, some of them with value semantics (i.e. they represent a value and have no other state). These can be allocated like normal C++ classes and are mostly passed by references.
For a Java head there's also the important concept of const correctness to learn. In C4D, const correctness is only used with SDK objects and thus only with references. The difference between "const String& str" and just "String& str" is that the former cannot be altered. This is so because C++ forbids any calls to "str" that aren't const qualified. For example "GetLength() const" is allowed, "Delete()" isn't. This way you can reap all the performance benefits of passing by reference/pointer without having to worry about the function modifiying your object. This both protects against logical errors when programming and acts as a self documentation of the code.
(I guess these are the kinds of thing one philosophizes upon after having to use the C++ SDK for a couple of years... :-)
As for your question, here's a code example from MSA: (A bit unpedagogic since it uses the other form of GetBool(), but you'll see what I mean with CToD() and DToC().)
class MSATextDialog : public GeModalDialog
{
public:
virtual Bool CreateLayout();
virtual Bool InitValues();
void ContainerToDialog();
void DialogToContainer();
virtual Bool Command(LONG id, const BaseContainer& msg);
BaseContainer bc;
};
Bool MSATextDialog::CreateLayout()
{
return LoadDialogResource(MSA_TEXT_DIALOG, NULL, 0);
}
Bool MSATextDialog::InitValues()
{
ContainerToDialog(); // Fill all values
return TRUE;
}
void MSATextDialog::ContainerToDialog()
{
SetString(RESULT_NAME, bc.GetString(RESULT_NAME, "MSA Text"));
SetMeter(TEXT_HEIGHT, bc.GetReal(TEXT_HEIGHT, 0.0));
SetBool(CENTER_TEXT, bc.GetBool(CENTER_TEXT));
}
void MSATextDialog::DialogToContainer()
{
GetString(RESULT_NAME, &bc, RESULT_NAME);
GetReal(TEXT_HEIGHT, &bc, TEXT_HEIGHT);
GetBool(CENTER_TEXT, &bc, CENTER_TEXT);
}
Bool MSATextDialog::Command(LONG id, const BaseContainer& msg)
{
DialogToContainer(); // Get all values
return TRUE;
}
Bool MSATextMenuPlugin::Execute(BaseDocument* doc)
{
BaseObject* obj = doc->GetActiveObject();
if (!obj)
{
MessageDialog(ERROR_SELECT_OBJECT_TEXT);
return FALSE;
}
BaseContainer bc;
bc.SetData(RESULT_NAME, obj->GetName() + " MSA");
// Bring up the dialog
MSATextDialog dialog;
dialog.bc = bc;
dialog.Open();
// Check the result
if (!dialog.GetResult()) return FALSE;
else bc = dialog.bc;
// Calling dialog.GetBool() here wouldn't work...
DoMSAText(doc, obj, bc);
return TRUE;
}