Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use C#-like attributes in C++

I'm considering the use of C++ for a personal project. I would like to make it platform independent (no Mono please, since some platforms don't yet support it), and that's why I considered C++.

I have one doubt, however. I've grown quite fond of C#'s attributes, and I would like to know if I can use something similar in C++.

Also, is it possible to use the decorator pattern for this?

EDIT: I would now consider other possibilities or approximations for this matter, ie. some way to attach additional behavior to a class in runtime.

EDIT 2: Java is not an option, because some devices I'd like to port it to don't support java.

like image 798
changelog Avatar asked Jul 11 '09 19:07

changelog


People also ask

How is C used?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

How do I use C on my computer?

It is a bit more cryptic in its style than some other languages, but you get beyond that fairly quickly. C is what is called a compiled language. This means that once you write your C program, you must run it through a C compiler to turn your program into an executable that the computer can run (execute).

How do I start C programming?

To start using C, you need two things: A text editor, like Notepad, to write C code. A compiler, like GCC, to translate the C code into a language that the computer will understand.

What does %c mean in C?

%d is used to print decimal(integer) number ,while %c is used to print character . If you try to print a character with %d format the computer will print the ASCII code of the character.


4 Answers

To "attach additional behavior to a class in runtime" in most any OO language I recommend the Strategy design pattern -- have the class (and/or its instances) hold (through a pointer in C++, a [reseatable] reference in other languages) an instance of a suitable interface / abstract class known as the "strategy interface" (with one method [virtual in C++ of course, non-final in languages that have final, etc -- IOW, an overridable method!-)] per point of extensibility), and generally supply getter and setter methods (or properties or whatever's appropriate to the specific language) to access and change that instance.

Lastly, the class or instance must delegate all appropriate functionality through the methods of the strategy interface instance it's holding.

I often recommend this "high-ceremony" approach (for this specific purpose) even in dynamic languages such as Python or Ruby which would also allow more informal approaches via duck typing and the ability of an object of class to directly reach into the internals of another -- such dynamic abilities are generally speaking quite useful, but for this specific purpose (as I think of "changing a class behavior at runtime") a more highly architected and controlled approach, in my experience, leads to better-maintainable and clearer code (this bit is controversial: many developers in dynamic-language communities like "monkey patching" approaches even in such situations, but a dozen years of successful development practice in dynamic languages, mostly Python, have made me otherwise inclined).

In appropriate case you can modify the fundamental Strategy DP approach in various ways; for example, when the modifiable functionality falls neatly into a few cohesive groups, it's best to "fragment" the Strategy object into several simple and cohesive ones (DrawingStrategy, PersistenceStrategy, BusinessRulesStrategy, and so forth).

This whole approach does not take the place of performing proper analysis and consequently proper design, as it won't allow extension of a class functionality along an axis that was not originally taken into consideration; rather, the approach is intended as a proper way to architect a well-thought-out design, providing "hooks" for extensibility in a well-controlled manner. If new considerations come into play it may still well be necessary to iterate and perfect the classes' design to cover such new ideas. But then, iterative development (including tweaks and extensions to the original design) is inevitable in any rich, complex real-world project -- the Strategy DP is just one arrow in your quiver to help make the process more orderly and effective.

like image 198
Alex Martelli Avatar answered Oct 17 '22 20:10

Alex Martelli


For class attributes, yes. Just define a base class called Attributes to store the attribute information, and inherit it in any class that needs attributes. You can query for it using RTTI cast.

But for method or parameter attributes, that's basically not an option.

like image 34
Daniel Earwicker Avatar answered Oct 17 '22 22:10

Daniel Earwicker


Build yourself a preprocessor that turns an attribute like syntax into actual properties, and methods.

like image 3
Christopher Karper Avatar answered Oct 17 '22 21:10

Christopher Karper


An idea on how to "simulate" a class attribute using template specialization:

#include <string>
#include <iostream>

// attribute classes: the default implementation returns some
// default values for the attributes properties
template<typename TheClass> 
struct Attribute1{
    static const int Value = 0;
};

template<typename TheClass> 
struct Attribute2{
    static const std::string Value(){
        return "";
    }
};

The default implementation of the attributes will be picked up by the compiler for a class without attributes:

// define a type without attributes
struct ClassWithoutAttributes{
};

If we want to apply the attributes to a class, we use template specialization:

// define a type with attributes; we "simulate" the attributes     
// template specialization
struct ClassWithAttributes{
};

// template-specialize Attribute1 for the class we want to apply the
// attribute to...
template<>
struct Attribute1<ClassWithAttributes>{
    static const int Value = 1;
};

// template-specialize Attribute2 
template<>
struct Attribute2<ClassWithAttributes>{
    static const std::string Value(){
        return "SomeString";
    }
};

We must apply (template-specialize) the attributes for every class we want them to be applied to:

class Item{
};

template<>
struct Attribute1<Item>{
    static const int Value = 2;
};

Example:

// how to use the fake attributes:
void main(){
    // no template specialization for "ClassWithoutAttributes" => the compiler picks up the "default" values
    std::cout << "Attribute1 for type 'ClassWithoutAttributes' : " << Attribute1<ClassWithoutAttributes>::Value << std::endl;
    std::cout << "Attribute2 for type 'ClassWithoutAttributes' : " << Attribute2<ClassWithoutAttributes>::Value() << std::endl;
    // here the compiler picks up the attribute classes specialized for "ClassWithAttributes"
    std::cout << "Attribute1 for type 'ClassWithAttributes' : " << Attribute1<ClassWithAttributes>::Value << std::endl;
    std::cout << "Attribute2 for type 'ClassWithAttributes' : " << Attribute2<ClassWithAttributes>::Value() << std::endl;
}

In this way the attributes are "applied" to the class, and not to the instance as with multiple inheritance; the fundamental difference, anyway, is that in this case the attributes are evaluated at compile time, and not at run time.

EDIT: modified the example to show how to apply several attributes to a class and how to apply the same attribute to several classes.

Answering this question has been fun for me; at this point, anyway, I feel that the best advice on the subject is that you should not try to program in c++ as if it was c#. In any case, happy coding!

like image 3
Paolo Tedesco Avatar answered Oct 17 '22 22:10

Paolo Tedesco