Data encapsulation

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • arnaudk
    Contributor
    • Sep 2007
    • 425

    #1

    Data encapsulation

    I have a method which needs to pass some data to the constructors of two other objects. The data is of different types, like a string, an int, etc. I have 12 fields in total.

    Rather than write inextensible constructors taking 12 arguments, I decided to make a new class of "DataPacket " objects which will hold the output of the method. These DataPacket objects are then passed to constructors of the other objects. Now, I came up with two prototypes for DataPacket. They both work fine but strike me messy.

    The first is const-correct. It is initialized using a 12-argument constructor and the data it contains is subsequentally accessed using its public methods f1(), etc.
    [code=cpp]
    class DataPacket
    {
    public:
    DataPacket(cons t string& field1, const int& field2, ... const int field12)
    : _field1(field1) , _field2(field2) , ... _field12(field1 2) {}

    string f1() const { return _field1;}
    int f2() const { return _field2;}
    ...
    double f12() const { return _field12;}

    private:
    const string _field1;
    const int _field2;
    ...
    const double _field12;
    }

    // To make packet:
    DataPacket data("Hello", 12, ..., 5.4351);

    // To read packet:
    string s = data.f1();
    ...
    [/code]

    The second is basically a struct. It members are explicitly set and can be subsequently accessed directly, but they can also be changed after its inception which is not desired behaviour.

    [code=cpp]
    class DataPacket
    {
    public:
    string field1;
    int field2;
    ...
    double field12;
    }

    // To make packet:
    DataPacket dp = { "Hello", 12, ..., 5.4351 };

    // To read packet:
    string s = dp.field1
    ...
    [/code]

    I like the simplicity of the second but not the fact that its contents can be later modified. This is prevented in the first version, but that contains a number of trivial functions which strike me as reduntant and I don't like its 12-argument constructor.

    Passing many arguments to a function must be a common problem, does anybody have nice solutions which work like passing and casting into meaningful types a pointer to void in C, but using proper C++ techniques, passing data-encapsulating objects instead?
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    The DataPacket approach is the wrong approach. That design looks very like Microsoft's VARIANT. I wouldn't use it.

    Instead use objects to replace arguments. For example, suppose your class has a Date object as a member. Rather than have three arguments for the month, day and year, have one Date argument.

    Then create a Date, pass it by reference to your constrcutor and let the Date copy constructor take care of making a copy for your object.

    [code=cpp]
    class MyClass
    {
    private:
    Date dt;

    public:
    MyClass(const Date& arg);
    };

    MyClass::MyClas s(const Date& arg) : dt(arg)
    {

    }

    int main()
    {
    Date data(7,4,1776);
    MyClass obj(data);
    }
    [/code]


    This is especially important shouild the Date class get re-designed where the three int arguiments get replaced by a string. If you have a Date& argument in your MyClass constructor, you don't care about the change. Only the code in main() will be affected. If you have three int arguments in MyClass, then you have welded MyClass to a particular version of the Date class. And that means you are on your way to monolithic code.

    Comment

    • arnaudk
      Contributor
      • Sep 2007
      • 425

      #3
      Thanks for your reply!
      Well, yes, DataPacket is the very object which I shall pass as an argument. So I think you're saying I should group the contents of DataPacket itself into smaller objects, basically smaller versions of DataPacket?

      But what about the large number of get/set functions, is this normal?

      At the moment, I have settled with an object encapsulating constant members which are set in the constructor's initialisation list. Then I can access them simply using the member operator "." and not get() functions, yet they can not be inadvertently changed, which is what I want.

      Comment

      Working...