Autor Beitrag
stiftmaster
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 149



BeitragVerfasst: Sa 01.07.06 14:42 
Hallo Leute,

in Delphi verwende ich bei Klassen immer die property-Eigenschaft (kurzes Beispiel):

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
type = Blub(class)
private
 string: fName;
 SetName(string Value);
public
property string: Name write SetName;


Durch die Uni bin "gezwungen" mir C++ anzueignen. Leider habe ich dort die Verwendung von properties nicht wirklich gefunden. Gibt es so etwas dort - oder wie codet man dort so etwas sauber?

Dankend

Stefan
AndyB
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1173
Erhaltene Danke: 14


RAD Studio XE2
BeitragVerfasst: Sa 01.07.06 15:22 
user profile iconstiftmaster hat folgendes geschrieben:
Leider habe ich dort die Verwendung von properties nicht wirklich gefunden. Gibt es so etwas dort - oder wie codet man dort so etwas sauber?

Properties gibt es nur bei Borland C++, weil Borland diese dem Compiler hinzugefügt haben. Der C++ Standard kennt keine Properties (zumindest noch nicht, auch wenn schon über verschiedene Entwürfe diskutiert wurden).

Man kann sie aber einigermaßen nachbilden:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
#include <iostream>

using namespace ::std;

class Test {
private:
  int m_index;
public:
  int index() { return m_index; }
  void setIndex(int value) { m_index = value; }
};

int main()
{
  Test t;
  t.setIndex(10);
  cout << t.index() << endl;
}

_________________
Ist Zeit wirklich Geld?
tommie-lie
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 4373

Ubuntu 7.10 "Gutsy Gibbon"

BeitragVerfasst: Sa 01.07.06 16:04 
user profile iconstiftmaster hat folgendes geschrieben:
Leider habe ich dort die Verwendung von properties nicht wirklich gefunden. Gibt es so etwas dort
Nein, C++ macht soetwas nicht.

stiftmaster hat folgendes geschrieben:
oder wie codet man dort so etwas sauber?
Über Setter und Getter:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
class Something
{
  public:
    SomeType getSomeField();
    void     setSomeField(SomeType value);
  protected: // oder private
    SomeType _SomeField;
}
Das ist der einfache Standard-Weg den jeder PRogrammierer kapiert und auch benutzt.
Wenn du unbedingt den Assign-Operator benutzen willst, bau dir eine Klasse und überlade ihn (ungetestet!):
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
class Something;

class SomeTypeProperty
{
  public
    Property(Something &parent) : _parent(parent) {};
    operator SomeType() const { return _parent.getSomeField(); }
    SomeTypeProperty &operator=(SomeType value) { _parent.SetSomeField(value); return *this; };
  private:
    Something &_parent;
}

class Something
{
  public:
    SomeType getSomeField();
    void     setSomeField(SomeType value);
    SomeTypeProperty SomeField;

    Something() : SomeField(this) {};
  protected: // oder private
    SomeType _SomeField;
}
Damit kannst du Something::SomeField wie ein DelphiLanguage-Property benutzen, dem du Variablen vom Typ SomeType zuweisen kannst.
Das Property kannst du dir in ein Template template<class C, typename T> verpacken und dann immer wieder instanzieren. Methodenpointer für Getter und Setter kannst du dann über den Konstruktor übergeben. Oder du holst noch weiter aus, schreibst dir einen netten Functor, implementierst deine Setter und Getter als Functor, kannst diese als Template-Parameter übergeben und hast keinerlei Property-Funktionalität mehr in Something::Something(), was eine gute Sache ist, aber manchmal eben ein wenig überzogen. Außerdem macht es deinen Code fett, weil für jedes Property mit unterschiedlichem Functor und Typ eine neue Template-Instanz erzeugt wird.
Ich kenne allerdings niemanden, der das so tatsächlich macht, außer vielleicht Leuten, die unbedingt Pascal-Denkweisen auf alle Sprachen anwenden müssen, selbst wenn's Assembler ist. Und das solltest du dir gar nicht erst angewöhnen.


Der Borland-C++-Compiler hat übrigens AFAIK ein __property-Macro, das aber nicht standard-konform ist und somit ein kaputtes ABI erzeugt (aber das tut der BCB für Win32 sowieso, wenn man libs erzeugt). Ansonsten gibt es Properties in C++ nur für C++/CLI, also wenn du für .NET programmierst.


Edit: Habe ich wirklich so lange gebraucht? :gruebel:

_________________
Your computer is designed to become slower and more unreliable over time, so you have to upgrade. But if you'd like some false hope, I can tell you how to defragment your disk. - Dilbert
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: So 02.07.06 18:55 
Ich bin zwar überhaupt kein C++-Fan, habe jedoch trotzdem mal diesen Code hier geschrieben ;) Über eine Hilfsklasse kann man es sich nämlich halbwegs zusammenbasteln. Ich rate aber von solchen Konstruktionen ab ;)
Wie ich erst jetzt sehe macht der Beitrag oberhalb eigentlich dasselbe. Hier aber noch als wiederverwertbares Template. Eigentlich genau das, was oben im zweiten Teil beschrieben wird ;) Interessant :D

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
// by delfiphan

#include <iostream>

using namespace std;

// Reusable class template. Could be stored in a separate header file. 
template <class BaseClass, class T, T(BaseClass::*getProc)(), void(BaseClass::*setProc)(T)>
class Property {
private:
  BaseClass* parent_;
public
  Property(BaseClass* parent) : parent_(parent) { }
  operator T() const { return (parent_->*getProc)(); }
  void operator=(T value) { (parent_->*setProc)(value); }
  friend BaseClass;
};

// Demonstration class with two properties "tag" and "boolProperty". 
class TTestClass {
private:
  // private fields for properties
  int FTag;
  bool FBoolProperty;

  // getter and setter functions
  int getTag() { return FTag; } 
  void setTag(int tag) { FTag = tag; }

  bool getLoggedBoolProperty() { 
    cout << "reading bool property..." << endl; 
    return FBoolProperty; 
  }
  void setLoggedBoolProperty(bool boolProperty) { 
    cout << "writing bool property..." << endl;  
    FBoolProperty = boolProperty; 
  }

  // property definitions
  typedef Property<TTestClass,int,getTag,setTag> Tag;
  typedef Property<TTestClass,bool,getLoggedBoolProperty,setLoggedBoolProperty> BoolProperty;
public:
  TTestClass() : tag(Tag(this)),boolProperty(BoolProperty(this)),FTag(0),FBoolProperty(false) {}
  Tag tag;
  BoolProperty boolProperty;
};

// demo
int main(int argc, char* arg[])
{
  TTestClass* myTest = new TTestClass();

  // Property-Test 1
  myTest->tag = 12;
  cout << myTest->tag << endl;

  // Property-Test 2
  myTest->boolProperty = false// Output: "writing bool property..."
  if (myTest->boolProperty) // Output: "reading bool property..."
    cout << "true"  << endl;
  else
    cout << "false"  << endl;
  ////

  delete myTest;
  cin.get();
  return 0;
}
tommie-lie
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 4373

Ubuntu 7.10 "Gutsy Gibbon"

BeitragVerfasst: So 02.07.06 19:11 
delfiphan: Ich hatte eigentlich kein fertiges Template zusammengetippselt, weil ich zu faul dazu war, und weil ich nicht wollte, daß er etwas fertiges hat, daß er einfach kopieren und wiederverwenden kann, weil ich nicht wollte, daß er sich sowas überhaupt angewöhnt. Und jetzt kommst du mit deinem Template daher :motz:
:tongue:

Aber zu welchem Zweck ist BaseClass ein friend der Property-Klasse?

_________________
Your computer is designed to become slower and more unreliable over time, so you have to upgrade. But if you'd like some false hope, I can tell you how to defragment your disk. - Dilbert
delfiphan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: So 02.07.06 20:24 
Naja. Ah ja friend kannst du weglassen. Das hatte ich beim "Entwickeln" der Klasse reingenommen und am Schluss nicht wieder gelöscht. Weswegen weiss ich auch nicht mehr (hab das Template nicht heute geschrieben).

Du hast schon Recht, sowas sollte man nicht brauchen... Aber für Lernzwecke kann man es ja zeigen ;)
stiftmaster Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 149



BeitragVerfasst: Mo 17.07.06 23:16 
Hi Leute,

sorry, dass ich mich erst so spät melde, hatte noch anderseitig zu tun :)

Vielen, vielen Dank für eure Beiträge - haben mir sehr geholfen. Ich bin zwar ein Delphi-Fan, das heißt aber nicht, dass ich versuche, diese Stile in andere Programmiersprachen zu integrieren. Möchte halt nur ein bisschen "vergleichen", damit ich die Sprachen besser auseinanderhalten kann :-)

Vielen Dank auch für die Templates - werde dies hoffentlich nie brauchen - weil das finde ich echt dreckig programmiert :-)

Schönen Abend

Stefan