Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I need to design, for a school project, a very simple GUI framework which needs to support the following controls/widgets: Window, Panel, Image, Label and Button.
The first question that came up to my mind is whether or not Window should be a control. I think it suppose to.
We have Window and Panel which can contain other controls. Button, Label and Image, cannot. So we need two basic types of controls; One which is a container and another which is not (I've seen that in Gtk implementation the later is also a container, but can only contain one single child. It's called GtkBin. I think it's an overhead for my simple project.
Third issue I came across with is: I need to traverse the UI tree (for the drawing) but since there's no mechanism for polymorphism in C, it's becoming somewhat problematic.
I thought about the following solution, utilizing union. Basically I'll need some function to convert a generic Control to it's actuall type.
typedef struct button {
char *image_path;
} Button;
typedef struct control_node {
Control *node;
struct control_node *next;
} ControlNode;
typedef struct panel {
ControlNode *children;
} Panel;
typedef union control_data {
Panel panel;
Button button;
} ControlData;
typedef struct control {
int x;
int y;
int type;
ControlData *data;
} Control;
So I'd like to get your thoughts about the issues I've introduced and an opinion about my current strategy (I am NOT looking for an implementation, rather thoughts/ideas etc)
Thanks.
You should put a void * first thing in the layout of every "GUI class" that will point to manually implemented v-tables for every type. The first function in every type's v-table could be one, returning a unique integer for every type (or just be a unique integer), so you can tell what is what and have some type safety implemented. Although it is not necessary, you could use the v-table pointer value to determine the type (since it will be unique), which will save on memory, but will be a little less obvious. It is also crucial to have virtualism in the object destruction, so a destructor function for handling each unique type's internals with its position in the v-table being consistent is also a must. Although for your task this might actually be avoidable, but for production it is a must.
As for the actual tree, this should be built on a simple parent-child relation, revolving around a leaf and node interface, the leaf only holding a pointer to the parent, the node also including a dynamic list type you must also implement. Then traversing the tree is fairly straightforward.
You can modularize a bit by using "interfaces" structs and aggregation in lieu of inheritance, but it won't save you much effort compared to implementing every type on its own, as long as you keep the v-table pointer the first object in the type layout, so that you know what you are working with and how to use it. The layout of the rest is not that crucial to follow any guidelines, as long as you know the type and cast the pointer to the appropriate struct type. But since every object will have a parent, even the root, which will be identifiable by its parent being 0, you really should put the parent second after the v-table pointer, this way you can avoid casting when all you need to access is the parent.
Another thing you can benefit from is using signals, as in have another pointer in every button, so you can assign it to a function to be executed when you "click" the button.
There are 2 different problems here: the conception of the GUI and its implementation in C. If conception is simpler in OO model, just write it that way. As first C++ compiler were just preprocessors for C code, C can implement OO modeling with the use of vtables.
First define clearly what are your objects (classes): which can be containers, which are drawables, which can react to mouse or keyboard events. What are their properties: text, x-y coordinates, bitmaps, and probably a z-coordinate. At the end of that phase, you should have a hierachy of classes with properties and methods, and possible overrides in subclasses - if you have learned it, UML could help for that part.
Second, you will have to implement that in C. Don't worry about it. You will not have the syntactic sugar of copy and move constructors for free, nor the notion of public, private and protected attributes, but struct can contain sub-objects, pointers to other structs and pointer to functions.
You just need a lexicon to translate OO tools in C :
class: struct
field of class: field of struct
method of class: function whose first attribute is a pointer to an instance of the struct
virtual method : pointer to a method
constructor and destructor : special methods that must be called explicitely - no automatic destruction if a struct goes out of scope
A non final class (contains virtual methods) should contain a VTABLE, which is a mere array of pointers to the virtual methods. This VTABLE should be first element of struct to ease class pointer casting. A derived class first contains its own vtable (if it is not final), then its attributes and then an instance of its parent. A cast from parent to derived pointer is just a matter of adding an offset. If you need multiple inheritance, you add the other parents after the first in the struct. Virtual inheritance would be slightly tougher to implement because it involves pointers in the VTABLE. Same if you need class aware objects, just add a constant in the VTABLE. But I do not think that you need all that for your requirement.
So look twice if you really want the harder bits: multiple inheritance and class aware objects, then just implement each class in its .h + .c file. You even get for free private methods: they are just static functions.
Related
I already have, say, a struct smallbox with two primitive variables (int identifier, int size) in it. This smallbox is part of higher structs that are used to build i.e. queues.
Now, I have in a part of my project an issue for which I came up with the solution to expand this smallbox, so it has another piece of information like int costs_to_send_it. While, I am not allowed to change my basis structs, is there a way to expand this struct in some fashion like methods overloading in java or so? Will I still be able to use all operation that I have on my higher structs while having the new struct smallbox with the new attribute inside instead of the old one?
This sentence determines the answer: “[Will] I still be able to use all operation that I have on my higher structs while having the new struct smallbox with color attribute inside instead of the old one?” The answer is no.
If the headers and routines involved were completely separate, there are some compiling and linking “games” you could play—compiling one set of source files with one definition of the structure and another set of source files with another definition of the structure and ensuring they never interacted in ways depending on the structure definition. However, since you ask whether the operations defined using one definition could be used with the alternate definition, you are compelling one set of code to use both definitions. (An alternate solution would be to engineer one source file to use different names for its routines under different circumstances, and then you could compile it twice, once for one definition of the structure and once for another, and then you could use the “same” operations on the different structures, but they would actually be different routines with different names performing the “same” operation in some sense.)
While you could define the structure differently within different translation units, when the structure or any type derived from it (such as a pointer to the structure) is used with a routine in a different translation unit, the type the routine is expecting to receive as a parameter must be compatible with the type that is passed to it as an argument, aside from some rules about signed types, adding qualifiers, and so on that do not help here.
For two structures to be compatible, there must be a one-to-one correspondence between their members, which must themselves be of compatible types (C 2018 6.2.7 1). Two structures with different numbers of members do not have a one-to-one correspondence.
is there a way to expand this struct in some fashion like methods
overloading in java or so?
In method overloading, the compiler chooses among same-named methods by examining the arguments to each invocation of a method of that name. Observe that that is an entirely localized decision: disregarding questions of optimization, the compiler's choice here affects only code generation for a single statement.
Where I still be able to use all operation
that I have on my higher structs while having the new struct smallbox
with color attribute inside instead of the old one?
I think what you're looking for is polymorphism, not overloading. Note well that in Java (and C++ and other the other languages I know of that support this) it is based on a type / subtype relationship between differently-named types. I don't know of any language that lets you redefine type names and use the two distinct types as if they were the same in any sense. Certainly C does not.
There are some alternatives, however. Most cleanly-conforming would involve creating a new, differently-named structure type that contains an instance of the old:
struct sb {
int id;
int size;
};
struct sb_metered {
struct sb box;
int cost;
}
Functions that deal in individual instances of these objects by pointer, not by value, can be satisfied easily:
int get_size(struct sb *box) {
return sb->size;
}
int get_cost(struct sb_metered *metered_box) {
return metered_box->cost;
}
int main() {
struct sb_metered b = { { 1, 17}, 42 };
printf("id: %d, size: %d, cost: %d\n",
b.id,
get_size(&b.box),
get_cost(&b));
}
Note that this does not allow you to form arrays of the supertype (struct sb) that actually contain instances of the subtype, nor to pass or return structure objects of the subtype by value as if they were objects of the supertype.
Say I'm writing an adventure game. The map is built of tiles of different types. I have tiles that form paths, and tiles that form doors, and so on.
I will use a struct to describe the type and content of a tile, and to which other tiles it connects.
Then I'll make a quadruple-linked list to connect them all together.
But a struct that will describe a room will have far more elements than one that will describe a door, so many elements in a door struct will be redundant. I could make a smaller door struct, but structs can only point to structs of the same type*, so I couldn't connect a room struct to a door struct. The redundancy may be negligible but I wondered if there's another way.
Another option is using an array of structs, but then I'd have lots of 'padding' structs wasting even more space. However an array would make reading and re-building a map from file much easier.
Is there any way around the limitation that a struct can only point to a struct of the same type? Or is there another common solution to this problem that I haven't mentioned?
One idea I had was that each tile could have pointers for every other type of tile. Some would be redundant, but it would be a lesser redundancy that the option above.
*By this I mean that typically in a linked list, structs contain pointers to struct of the same type that they're in.
You really don't have to have a uniform struct describing everything. Instead, you could do the following (this is somewhat like writing your own C++ virtual tables in C, and is very widely used).
Your basic tile struct can look like this:
struct tile
{
// common tile stuff
...
enum tile_type type;
void *type_info;
};
So in this struct you store stuff that's common to every tile type. Then you make other structs for other types: one for a room, one for a path, etc. Within an object of tile, you make the enum describe the actual type, and store a pointer to the concrete type within the void *.
There are many links describing variations of this technique. Here's one.
Instead of storing elements in a tile, store only a pointer to the linked list of elements.
I need to do a home assignment in VC++, which uses ADT to do several operations on an integer list. For now, we're not allowed to use classes, so I need to use struct.
I don't quite understand how ADTs work, so I'm not sure where to start, because all tutorials on the internet use classes, which I don't want to.
So are there any tutorials on the net that: 1. explain the concept of Abstract Data Types and 2. Provide an example of implementation (preferably in C++ and not using class, but struct instead).
I will give a try for an answer that is more what is my understanding.
What is an abstract datatype?
Always my first shot: Look at http://en.wikipedia.org/wiki/Abstract_data_type
My "practical" understanding of this is: There is some idea of an object that is defined by the object, its variables (or data) and the operations that are defined on this object.
For your case the object is a list of integers. The operations are something like insert a new integer, remove an integer, get the number of integers stored in the list and so on. When implementing this datatype you have to write this operations as functions. To provide this functions you will have to make up some structure to save the data to operate on.
Provide an example of implementation.
Well I won't do your homework so I will do some pseudocode:
struct ListElement {
int value;
type NextElement; //i leave the type to you
};
void insertBehind(ListElement &element, int newValue)//this is one way to do this
{
ListElement newElement(newValue); //create the new element (use new instead, don't want to "spoiler" the type to you)
newElement.nextElement = element.nextElement; //set the next element of this new one
element.NextElement = newElement; //set the new element
}
...
What distinguishes and object from a struct?
When and why do we use an object as opposed to a struct?
How does an array differ from both, and when and why would we use an array as opposed to an object or a struct?
I would like to get an idea of what each is intended for.
Obviously you can blur the distinctions according to your programming style, but generally a struct is a structured piece of data. An object is a sovereign entity that can perform some sort of task. In most systems, objects have some state and as a result have some structured data behind them. However, one of the primary functions of a well-designed class is data hiding — exactly how a class achieves whatever it does is opaque and irrelevant.
Since classes can be used to represent classic data structures such as arrays, hash maps, trees, etc, you often see them as the individual things within a block of structured data.
An array is a block of unstructured data. In many programming languages, every separate thing in an array must be of the same basic type (such as every one being an integer number, every one being a string, or similar) but that isn't true in many other languages.
As guidelines:
use an array as a place to put a large group of things with no other inherent structure or hierarchy, such as "all receipts from January" or "everything I bought in Denmark"
use structured data to compound several discrete bits of data into a single block, such as you might want to combine an x position and a y position to describe a point
use an object where there's a particular actor or thing that thinks or acts for itself
The implicit purpose of an object is therefore directly to associate tasks with the data on which they can operate and to bundle that all together so that no other part of the system can interfere. Obeying proper object-oriented design principles may require discipline at first but will ultimately massively improve your code structure and hence your ability to tackle larger projects and to work with others.
Generally speaking, objects bring the full object oriented functionality (methods, data, virtual functions, inheritance, etc, etc) whereas structs are just organized memory. Structs may or may not have support for methods / functions, but they generally won't support inheritance and other full OOP features.
Note that I said generally speaking ... individual languages are free to overload terminology however they want to.
Arrays have nothing to do with OO. Indeed, pretty much every language around support arrays. Arrays are just blocks of memory, generally containing a series of similar items, usually indexable somehow.
What distinguishes and object from a struct?
There is no notion of "struct" in OOP. The definition of structures depends on the language used. For example in C++ classes and structs are the same, but class members are private by defaults while struct members are public to maintain compatibility with C structs. In C# on the other hand, struct is used to create value types while class is for reference types. C has structs and is not object oriented.
When and why do we use an object as opposed to a struct?
Again this depends on the language used. Normally structures are used to represent PODs (Plain Old Data), meaning that they don't specify behavior that acts on the data and are mainly used to represent records and not objects. This is just a convention and is not enforced in C++.
How does an array differ from both,
and when and why would we use an
array as opposed to an object or a
struct?
An array is very different. An array is normally a homogeneous collection of elements indexed by an integer. A struct is a heterogeneous collection where elements are accessed by name. You'd use an array to represent a collection of objects of the same type (an array of colors for example) while you'd use a struct to represent a record containing data for a certain object (a single color which has red, green, and blue elements)
Short answer: Structs are value types. Classes(Objects) are reference types.
By their nature, an object has methods, a struct doesn't.
(nothing stops you from having an object without methods, jus as nothing stops you from, say, storing an integer in a float-typed variable)
When and why do we use an object as opposed to a struct?
This is a key question. I am using structs and procedural code modules to provide most of the benefits of OOP. Structs provide most of the data storage capability of objects (other than read only properties). Procedural modules provide code completion similar to that provided by objects. I can enter module.function in the IDE instead of object.method. The resulting code looks the same. Most of my functions now return stucts rather than single values. The effect on my code has been dramatic, with code readability going up and the number of lines being greatly reduced. I do not know why procedural programming that makes extensive use of structs is not more common. Why not just use OOP? Some of the languages that I use are only procedural (PureBasic) and the use of structs allows some of the benefits of OOP to be experienced. Others languages allow a choice of procedural or OOP (VBA and Python). I currently find it easier to use procedural programming and in my discipline (ecology) I find it very hard to define objects. When I can't figure out how to group data and functions together into objects in a philosophically coherent collection then I don't have a basis for creating classes/objects. With structs and functions, there is no need for defining a hierarchy of classes. I am free to shuffle functions between modules which helps me to improve the organisation of my code as I go. Perhaps this is a precursor to going OO.
Code written with structs has higher performance than OOP based code. OOP code has encapsulation, inheritance and polymorphism, however I think that struct/function based procedural code often shares these characteristics. A function returns a value only to its caller and only within scope, thereby achieving encapsulation. Likewise a function can be polymorphic. For example, I can write a function that calculates the time difference between two places with two internal algorithms, one that considers the international date line and one that does not. Inheritance usually refers to methods inheriting from a base class. There is inheritance of sorts with functions that call other functions and use structs for data transfer. A simple example is passing up an error message through a stack of nested functions. As the error message is passed up, it can be added to by the calling functions. The result is a stack trace with a very descriptive error message. In this case a message inherited through several levels. I don't know how to describe this bottom up inheritance, (event driven programming?) but it is a feature of using functions that return structs that is absent from procedural programming using simple return values. At this point in time I have not encountered any situations where OOP would be more productive than functions and structs. The surprising thing for me is that very little of the code available on the internet is written this way. It makes me wonder if there is any reason for this?
Arrays are ordered collection of items that (usually) are of the same types. Items can be accessed by index. Classic arrays allow integer indices only, however modern languages often provide so called associative arrays (dictionaries, hashes etc.) that allow use e.g. strings as indices.
Structure is a collection of named values (fields) which may be of 'different types' (e.g. field a stores integer values, field b - string values etc.). They (a) group together logically connected values and (b) simplify code change by hiding details (e.g. changing structure layout don't affect signature of function working with this structure). The latter is called 'encapsulation'.
Theroretically, object is an instance of structure that demonstrates some behavior in response to messages being sent (i.e., in most languages, having some methods). Thus, the very usefullness of object is in this behavior, not its fields.
Different objects can demonstrate different behavior in response to the same messages (the same methods being called), which is called 'polymorphism'.
In many (but not all) languages objects belong to some classes and classes can form hierarchies (which is called 'inheritance').
Since object methods can work with its fields directly, fields can be hidden from access by any code except for this methods (e.g. by marking them as private). Thus encapsulation level for objects can be higher than for structs.
Note that different languages add different semantics to this terms.
E.g.:
in CLR languages (C#, VB.NET etc) structs are allocated on stack/in registers and objects are created in heap.
in C++ structs have all fields public by default, and objects (instances of classes) have all fields private.
in some dynamic languages objects are just associative arrays which store values and methods.
I also think it's worth mentioning that the concept of a struct is very similar to an "object" in Javascript, which is defined very differently than objects in other languages. They are both referenced like "foo.bar" and the data is structured similarly.
As I see it an object at the basic level is a number of variables and a number of methods that manipulate those variables, while a struct on the other hand is only a number of variables.
I use an object when you want to include methods, I use a struct when I just want a collection of variables to pass around.
An array and a struct is kind of similar in principle, they're both a number of variables. Howoever it's more readable to write myStruct.myVar than myArray[4]. You could use an enum to specify the array indexes to get myArray[indexOfMyVar] and basically get the same functionality as a struct.
Of course you can use constants or something else instead of variables, I'm just trying to show the basic principles.
This answer may need the attention of a more experienced programmer but one of the differences between structs and objects is that structs have no capability for reflection whereas objects may. Reflection is the ability of an object to report the properties and methods that it has. This is how 'object explorer' can find and list new methods and properties created in user defined classes. In other words, reflection can be used to work out the interface of an object. With a structure, there is no way that I know of to iterate through the elements of the structure to find out what they are called, what type they are and what their values are.
If one is using structs as a replacement for objects, then one can use functions to provide the equivalent of methods. At least in my code, structs are often used for returning data from user defined functions in modules which contain the business logic. Structs and functions are as easy to use as objects but functions lack support for XML comments. This means that I constantly have to look at the comment block at the top of the function to see just what the function does. Often I have to read the function source code to see how edge cases are handled. When functions call other functions, I often have to chase something several levels deep and it becomes hard to figure things out. This leads to another benefit of OOP vs structs and functions. OOP has XML comments which show up as tool tips in the IDE (in most but not all OOP languages) and in OOP there are also defined interfaces and often an object diagram (if you choose to make them). It is becoming clear to me that the defining advantage of OOP is the capability of documenting the what code does what and how it relates to other code - the interface.
How can I create an array of namespaces? And because it seems like a long shot, if this is impossible, is there something similar to a namespace that can be made into an array?
The namespace, if it helps, contains these variables:
const int maxx=// depends on the particular namespace
// I need an array to go through each namespace and
// pick out the variable
const int maxy=// depends on particular namespace
//prgm is a class I made
prgm sector[maxx][maxy];
// another array of prgms. int is my shorthand of saying "depends on
// particular namespace", so is char.
prgm programs[int]={prgm1(int,int,char),prgm2(int,int,char)...
So any help would be welcome.
You could use reflection, but I think you should rethink your design.
I am not sure what language you are talking about, but in many (most?) languages, references to constants are replaced by the constant value at compile time. So they are no longer present at runtime and even reflection won't help.
You could create a class in each namespace that exposes the constants as (static) properties. Then you can use reflection to search the class in each namespace and obtain the constant values from the properties.
But, as mentioned by others, you should really rethink your design. Finally, namespaces are usually not accessable via reflection because they just extend the class names of the contained classes (and other stuff). Or is there a (non-esoteric) language that exposes namespaces as entities via reflection?
For .NET the reference for the System.Type.Namespace property states the following.
A namespace is a logical design-time naming convenience, used mainly to define scope in an application and organize classes and other types in a single hierarchical structure. From the viewpoint of the runtime, there are no namespaces.
Is this supposed to be C++? Sounds like you need to define a class, not a namespace, then create instances (objects) of that class and put them in an array.
So the sector variable gets tricky, since it is sized based on the value of maxx and maxy parameters that would be passed to the constructor of the class. You can take care of that problem by using a container class or a dynamically-allocated multi-dimensional array instead.
If you talk about C++, in there you can't pass namespaces as entities around. But you can do so with types, as type argument to templates. In this case, an MPL sequence could help together with MPL algorithms:
struct c1 { typedef int_<2> value_x; };
struct c2 { typedef int_<3> value_x; };
struct c3 { typedef int_<1> value_x; };
template<typename C> struct get_x : C::value_x { };
typedef vector<c1, c2, c3> scope_vec;
typedef max_element<
transform_view< scope_vec , get_x<_1> >
>::type iter;
You may then create your array like
prgm programs[deref< iter >::type::value];
Note that the search within that type-vector happens at compile time. So the value of the array is determined at compile time either.