CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7
  1. #1
    Join Date
    Apr 2009
    Posts
    1,355

    my own property code

    i build these property code:
    Code:
    template <typename T>
    class property
    {
    private:
        T PropertyValue;
        std::function<T(void)> getf;
        std::function<void(T)> setf;
    public:
    
        property(T value)
        {
            PropertyValue=value;
        };
    
        property(std::function<T(void)> GetFunction=nullptr,std::function<void(T)> SetFunction=nullptr)
        {
            setf=SetFunction;
            getf=GetFunction;
        }
    
        property& operator=(T value)
        {
            if(getf==nullptr || setf==nullptr)
                PropertyValue=value;
            else
                setf(value);
            return *this;
        }
    
        T& operator=(property value)
        {
            if(value.getf==nullptr || value.setf==nullptr)
                return value.PropertyValue;
            else
                return value.getf();
        }
    
    
        friend ostream& operator<<(ostream& os, const property& dt)
        {
            if(dt.getf==nullptr && dt.setf==nullptr)
                os << dt.PropertyValue;
            else if (dt.getf!=nullptr)
                os << dt.getf();
            return os;
        }
    
        friend istream& operator>>(istream &input, property &dt)
        {
            input >> dt.PropertyValue;
            if (dt.setf!=nullptr)
                dt.setf(dt.PropertyValue);
            return input;
        }
    
        friend istream &getline(istream &in, property &dt)
        {
            getline(in, dt.PropertyValue);
            if (dt.setf!=nullptr)
                dt.setf(dt.PropertyValue);
            return in;
        }
    };
    but i'm getting unexepected results with these test:
    Code:
    class test
    {
    public:
        int x;
        int y;
        int getx()
        {
            return x;
        }
        void setx(int value)
        {
            x=value;
        }
        int gety()
        {
            return y;
        }
        void sety(int value)
        {
            y=value;
        }
    public:
        std::string go()
        {
            std::ostringstream out;
            out << '(' << x << ',' << y << ')' << ':' << x + y << '\n';
            return(out.str());
        }
    
    
        test()
        {
    
        }
        property<int> X=GetProperty<int>(&test::getx, &test::setx,this);
        //PROPERTY(int, X,test::getx, test::setx);
        PROPERTY(int, Y,test::gety, test::sety);
    };
    
    int main()
    {
        test a;
        cout << "what is the x?\n";
        cin >> a.X;
        cout << "what is the y?\n";
        cin >> a.Y;
        cout << "\nhere is the result:\n" << a.go() << '\n';
        test b = a;
        cout << b.x << "\t" << b.y << endl;
        cout << "what is a different x?\n";
        cin >> b.X;
        cout << "what is a different y?\n";
        cin >> b.Y;
        cout << "\nhere is the result:\n" << b.go() << '\n';
        cout << "\noh wait, no; here is the result:\n" << a.go() << '\n';
        return 0;
    }
    i belive is that my class isn't working with class instance\object pointer correctly
    but what i'm doing wrong in my class?

  2. #2
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: my own property code

    Quote Originally Posted by Cambalinho View Post
    i build these property code:
    ...
    but i'm getting unexepected results with these test:
    1. What did you expect and what did you get?
    2. Did you debug your code?
    Victor Nijegorodov

  3. #3
    Join Date
    Apr 2009
    Posts
    1,355

    Re: my own property code

    Quote Originally Posted by VictorN View Post
    1. What did you expect and what did you get?
    2. Did you debug your code?
    i fix that...
    the problem(see just the main() code) was that i used instance 'b' but changes on instance 'a'(like 'b' be aponted to 'a').
    i did a Copy Construtctor, in the test class, for avoid copy the 'this', when we do:
    Code:
    test a;
    test b=a;
    heres the code corrected:
    Code:
    //proeprty.h
    /*
    - how use create 1 property with macro:
    
          PROPERTY(TypeName,PropertyName,getfunction, setfunction)
    
    - never forget to do 1 Copy Constructor inside of class's, that uses the property,
             for avoid copy the 'this' value\adress and use a diferent memory adress
    */
    
    #ifndef PROPERTY_H
    #define PROPERTY_H
    
    #include <iostream>
    #include <functional>
    
    using namespace std;
    
    template <typename T>
    class property
    {
    private:
        T PropertyValue;
        std::function<T(void)> getf;
        std::function<void(T)> setf;
    public:
    
        property(const T value)
        {
            this->getf=nullptr;
            this->setf=nullptr;
            this->PropertyValue=value;
        };
    
        property(const property &value)
        {
            PropertyValue=value.PropertyValue;
        };
    
        property(std::function<T(void)> GetFunction=nullptr,std::function<void(T)> SetFunction=nullptr)
        {
            this->setf=SetFunction;
            this->getf=GetFunction;
        }
    
        property& operator=(const T &value) const
        {
            if(this->getf==nullptr || this->setf==nullptr)
                this->PropertyValue=value;
            else
                this->setf(value);
            return *this;
        }
    
        T& operator=(const property &value) const
        {
            if(value.getf==nullptr || value.setf==nullptr)
                return value.PropertyValue;
            else
                return value.getf();
            return *this;
        }
    
        friend ostream& operator<<(ostream& os, property& dt)
        {
            if(dt.getf==nullptr && dt.setf==nullptr)
                os << dt.PropertyValue;
            else if (dt.getf!=nullptr)
                os << dt.getf();
            return os;
        }
    
        friend istream& operator>>(istream &input, property &dt)
        {
            input >> dt.PropertyValue;
            if (dt.setf!=nullptr)
                dt.setf(dt.PropertyValue);
            return input;
        }
    
        friend istream &getline(istream &in, property &dt)
        {
            getline(in, dt.PropertyValue);
            if (dt.setf!=nullptr)
                dt.setf(dt.PropertyValue);
            return in;
        }
    };
    
    template<typename T, typename Fnc1_t, typename Fnc2_t, typename classthis>
    property<T> GetProperty(Fnc1_t Getter, Fnc2_t Setter, classthis clsthis)
    {
        return property<T>(std::bind(Getter, clsthis), std::bind(Setter, clsthis, std::placeholders::_1));
    }
    
    #define PROPERTY(TypeName,PropertyName,getfunction, setfunction) \
    property<TypeName> PropertyName{std::bind(&getfunction, this),std::bind(&setfunction, this, std::placeholders::_1)}
    
    #endif //PROPERTY_H
    
    
    //main.cpp
    
    #include <iostream>
    #include <sstream>
    #include "property.h"
    
    using namespace std;
    
    class test
    {
    public:
        int x;
        int y;
        int getx()
        {
            return x;
        }
        void setx(int value)
        {
            x=value;
        }
        int gety()
        {
            return y;
        }
        void sety(int value)
        {
            y=value;
        }
        std::string go()
        {
            std::ostringstream out;
            out << '(' << x << ',' << y << ')' << ':' << x + y << '\n';
            return(out.str());
        }
    
        test()
        {
    
        }
    
        //the Copy constructor for avoid copy the 'this'
        test(const test &tea)
        {
            this->x=tea.x;
            this->y=tea.y;
        }
    
        PROPERTY(int, X, test::getx, test::setx);
        PROPERTY(int, Y, test::gety, test::sety);
    };
    
    int main()
    {
        test a;
        cout << "what is the x?\n";
        cin >> a.X;
        cout << "what is the y?\n";
        cin >> a.Y;
        cout << "\nhere is the result:\n" << a.go() << '\n';
        test b = a; //now the 'this' isn't copyied too
        cout << "what is a different x?\n";
        cin >> b.X;
        cout << "what is a different y?\n";
        cin >> b.Y;
        cout << "\nhere is the result:\n" << b.go() << '\n';
        cout << "\noh wait, no; here is the result:\n" << a.go() << '\n';
        return 0;
    }
    something that i have learned yesterdar, before i lose the electricity, because of the whether(rain)
    the problem wasn't my property code, that needs the 'this' pointer class... but in test class, because, by defauld, the compiler do a Copy Constructor(if we don't do it) and copy the 'this' too

  4. #4
    Join Date
    Apr 1999
    Posts
    27,449

    Re: my own property code

    Quote Originally Posted by Cambalinho View Post
    i fix that...
    the problem(see just the main() code) was that i used instance 'b' but changes on instance 'a'(like 'b' be aponted to 'a').
    i did a Copy Construtctor, in the test class, for avoid copy the 'this',
    Well, you've now made your class almost useless in a real program. You've now introduced side-effects in your copy-assignment operations.

    The purpose of the copy constructor (and assignment operator, which you didn't implement) is to do just that -- make copies. If you start to make fake copies of your objects using the copy-assignment operator, that opens the code up for a lot of runtime bugs that are insanely difficult to solve.

    In other words, what if I tried to create a vector<test> and started to manipulate this vector by resizing it, removing items, etc.? What will happen? Chaos.

    When creating a copy constructor and assignment operator, the goal is to make sure that the copied object behave exactly the same as the original object. In other words, if I take that copy and use it instead of the original object, the resulting program must behave exactly the same externally. For example:
    Code:
    #include <string>
    
    int main()
    {
       std::string s1 = "abc";
       std::string s2 = s1;
    }
    What if the implementors of std::string decided to add an extra character (maybe a blank) to s2 when a copy is made, thus making the length f s2 equal to 4 instead of 3? Then std::string would be totally unusable in any program except a toy one.

    Your property class itself implements the copy constructor with side-effects. Why didn't you copy the std::function members? You only copied the PropertyValue. So already you're in trouble.

    If you need to change the object to "almost copy" another object, then provide that function -- do not use the copy constructor or assignment operator for this purpose.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; February 7th, 2014 at 01:29 PM.

  5. #5
    Join Date
    Apr 2009
    Posts
    1,355

    Re: my own property code

    Quote Originally Posted by Paul McKenzie View Post
    Well, you've now made your class almost useless in a real program. You've now introduced side-effects in your copy-assignment operations.

    The purpose of the copy constructor (and assignment operator, which you didn't implement) is to do just that -- make copies. If you start to make fake copies of your objects using the copy-assignment operator, that opens the code up for a lot of runtime bugs that are insanely difficult to solve.

    In other words, what if I tried to create a vector<test> and started to manipulate this vector by resizing it, removing items, etc.? What will happen? Chaos.

    When creating a copy constructor and assignment operator, the goal is to make sure that the copied objects acts exactly the same as the original object. In other words, if I take that copy and use it instead of the original object, the code must behave exactly the same externally.

    Your property class itself implements the copy constructor with side-effects. Why didn't you copy the std::function members? You only copied the PropertyValue. So already you're in trouble.

    If you need to change the object to "almost copy" another object, then provide that function -- do not use the copy constructor or assignment operator for this purpose.

    Regards,

    Paul McKenzie
    "Why didn't you copy the std::function members?"
    because they are dependent of 'this' class... so how can i avoid that?

  6. #6
    Join Date
    Apr 1999
    Posts
    27,449

    Re: my own property code

    Quote Originally Posted by Cambalinho View Post
    "Why didn't you copy the std::function members?"
    because they are dependent of 'this' class... so how can i avoid that?
    That's your problem to solve.

    What I'm saying is that you are not to use the copy-assignment operator to do this. You are introducing side-effects in an operation that you have no exact control over when or where it will be used (the compiler can also call the copy constructor and/or assignment operator "behind your back").

    Again, look at my vector example. You can't use your property class in a vector safely (or any other container that makes copies).

    I know you're testing with toy programs, but you can't just look at your little program before making these decisions. You must look at the big picture. Realizing that your classes can't be used safely in containers should have been on your list of items you should have been aware of.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; February 7th, 2014 at 01:19 PM.

  7. #7
    Join Date
    Apr 1999
    Posts
    27,449

    Re: my own property code

    Quote Originally Posted by Cambalinho View Post
    so how can i avoid that?
    This shows that writing proper C++ classes takes a lot more thought than just picking up syntax here and there and throwing together a class that happens to compile. Your design is flawed, plain and simple.

    So that is your homework -- come up with a design that doesn't violate the rules of creating valid copies, but allows the user to "clone" another object. Yes, it takes thought (on paper, using UML, whatever), before writing any code. Once that's OK, then you implement the C++ class.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; February 7th, 2014 at 01:33 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured