Thread: Classes & Constructors

  1. #1
    Registered User
    Join Date
    Jul 2010
    Posts
    56

    Classes & Constructors

    first i coded this in C# (just so i could get warmed up with the basic stuff i learned from constructor lessons)

    Code:
    using System;
    
    namespace myProgram
    {
        class Person
        {
            private string name;
            private int age;
    
            public Person()
            {
                this.name = "Unknown";
                this.age = 0;
            }
    
            public Person(string name, int age)
            {
                this.name = name;
                this.age = age;
            }
    
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
    
            public int Age { get { return age; } set { this.age = value; } }
    
            public static void Introduce(Person obj)
            {
                Console.WriteLine("Hi, my name is "+obj.name+", I am "+obj.age+" years old.");
            }
        }
    
        class Program
        {
            public static void Main()
            {
                Person p1 = new Person();
                Person p2 = new Person("Jack Wilson",40);
                Person.Introduce(p1);
                Person.Introduce(p2);
            }
        }
    
    }
    it works as expected. Then I decided to translate it to C++, and this is the best i could come up with:

    Code:
    #include <iostream>
    using namespace std;
    
    class Person
    {
    
        private:
            string name;
            int age;
    
    
        public:
            Person();
            Person(string, int);
            string getName(){ return name; }
            int getAge(){ return age; }
    
            static void Introduce(Person);
    };
    
    Person::Person()
    {
        this->name = "Nameless";
        this->age = 0;
    }
    
    Person::Person(string name, int age)
    {
        this->name = name;
        this->age = age;
    }
    
    void Person::Introduce(Person obj)
    {
        cout<<"Hello, my name is "<<obj.getName()<<", I am "<<obj.getAge()<<" years old."<<endl;
    }
    
    int main()
    {
        Person p1 = Person();
        Person p2 = Person("Jack Wilson",40);
        Person::Introduce(p1);
        Person::Introduce(p2);
    }
    Which works, as well.
    Well then, i just posted this so that maybe you veterans could clue me in on how to make it cleaner.

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    "this->" is not needed inside your functions.
    You're missing set for age/name.
    You should use references where possible.
    Introduce should not be static (why would you do that?).
    And do not leave out parameter names:
    >>Person(string, int);
    should be:
    Person(const string& name, int age);

    >>Person p2 = Person("Jack Wilson",40);
    Better written as
    Person p2("Jack Wilson",40);

    And
    >>Person p1 = Person();
    as
    Person p1;
    No parentheses here! Doing so will not do what you expect.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by dhuan
    Which works, as well.
    Well then, i just posted this so that maybe you veterans could clue me in on how to make it cleaner.
    I would suggest something like this:
    Code:
    #include <string>
    
    class Person
    {
    public:
        Person() : name("Nameless"), age(0) {}
        Person(const std::string& name_, int age_) : name(name_), age(age_) {}
    
        std::string getName() const
        {
            return name;
        }
    
        int getAge() const
        {
            return age;
        }
    private:
        std::string name;
        int age;
    };
    
    #include <iostream>
    
    void introduce(const Person& person)
    {
        using namespace std;
        cout << "Hello, my name is " << person.getName()
            << ", I am " << person.getAge() << " years old." << endl;
    }
    
    int main()
    {
        Person p1;
        Person p2("Jack Wilson", 40);
        introduce(p1);
        introduce(p2);
    }
    Notice:
    • The #include <string>
    • The using directive was moved to after the class definition (and in fact made local to a function) since the class definition might eventually go into a header.
    • The use of construction initialiser lists.
    • The use of const reference parameter for std::string and Person types.
    • That getName and getAge were declared const.
    • That the static member function was changed to a free function since it can work through the interface of the class without accessing its internals.
    • The initialisation of the Person objects has been simplified.


    EDIT:
    Quote Originally Posted by Elysia
    You're missing set for age/name.
    Whether these are actually missing depends on whether objects of this Person class are designed to be immutable, but either way it is something to think about.
    Last edited by laserlight; 10-07-2010 at 01:22 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Registered User
    Join Date
    Jul 2010
    Posts
    56
    Thank you all for your answers.
    One thing though laserlight, I always thought that reference parameters should only be used when you want to modify the variable that's being passed. In this case, what's the use of referece parameters?

    void introduce(const Person& person)
    {

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    It avoids the overhead of copying the parameter. By specifying const, you make sure you don't accidentally modify it (among other things).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #6
    Nasal Demon Xupicor's Avatar
    Join Date
    Sep 2010
    Location
    Poland
    Posts
    179
    The point is - you avoid copying the object, which may hurt the performance of your program.
    edit: Ah, beat me to it.

  7. #7
    Registered User
    Join Date
    Jul 2010
    Posts
    56
    Got it.

    >>Person p2 = Person("Jack Wilson",40);
    Better written as
    Person p2("Jack Wilson",40);
    Does it change anything other than having to type less?

    And
    >>Person p1 = Person();
    as
    Person p1;
    No parentheses here! Doing so will not do what you expect.
    Won't it? What's the difference in this case? Won't both ways call the constructors?

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by dhuan View Post
    Does it change anything other than having to type less?
    Technically, it would create an object, a temporary, and assign it to the variable. Nevertheless, compilers would usually optimize that. So it usually amounts only to less typing.

    Won't it? What's the difference in this case? Won't both ways call the constructors?
    Consider:
    Code:
    Person p1(); // Function prototype for p1
    
    int main()
    {
        Person p1(); // Create p1 object.
        // ... Use p1 ...
    }
    
    Person p1() { return Person(); }
    Compare the function prototype and your p1 variable declaration. Similar, aren't they?
    So while it looks perfectly valid to create an object that way, it's really a pitfall in the language!
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Code:
    Person p1(); // Function prototype for p1
    Correct. As a matter of fact, that will always look like a function prototype to the compiler, it doesn't matter what context it appears. Leaving off the parens is not a matter of style. Further, if you must use a temporary to create another type of object, then:

    Foo x = Bar();

    is actually correct in C++'s grammar.

  10. #10
    Registered User
    Join Date
    Jul 2010
    Posts
    56
    Well, i've done some upgrades on my code based on what i learned from you guys (i still wanna leave that "Introduce" function as static, so i can can call it directly from the class.)


    Code:
    #include <iostream>
    using namespace std;
    
    class Person
    {
    
        private:
            string name;
            int age;
    
    
        public:
            Person();
            Person(string, int);
            string getName(){ return name; }
            int getAge(){ return age; }
    
            static void Introduce(const Person&);
    };
    
    Person::Person()
    {
        this->name = "Nameless";
        this->age = 0;
    }
    
    Person::Person(string name, int age)
    {
        this->name = name;
        this->age = age;
    }
    
    void Person::Introduce(const Person& obj)
    {
        cout<<"Hello, my name is "<<obj.getName()<<", I am "<<obj.getAge()<<" years old."<<endl;
    }
    
    int main()
    {
        Person p1;
        Person p2("Jack Wilson",40);
        Person::Introduce(p1);
        Person::Introduce(p2);
    }
    Now I seem to be having problem with this line:
    Code:
        cout<<"Hello, my name is "<<obj.getName()<<", I am "<<obj.getAge()<<" years old."<<endl;
    This is what the compiler says:

    error: passing `const Person' as `this' argument of `std::string Person::getName()' discards qualifiers|
    Last edited by dhuan; 10-07-2010 at 08:55 PM.

  11. #11
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    The Introduce function uses const references when it calls the stuff on that line. In order to be const correct, the compiler enforces a rule that const objects only use const methods. When you have a method that does not change the object, you modify it with const like so:

    Code:
            string getName() const { return name; }
            int getAge() const { return age; }
    Then const objects can use it without an error.

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Code suggestions:

    Code:
    #include <iostream>
    using namespace std;
    
    class Person
    {
    
        private:
            string m_name;
            int m_age;
    
    
        public:
            Person();
            Person(string name, int age);
            string getName() const { return m_name; }
            int getAge() const { return m_age; }
            string SetName(const std::string& name) { m_name = name; }
            int SetAge(int age) { m_age = age; }
    
            void Introduce() const;
    };
    
    Person::Person(): m_name("Nameless"), m_age(0)
    {
    }
    
    Person::Person(string name, int age): m_name(name), m_age(age)
    {
    }
    
    void Person::Introduce()
    {
        cout<<"Hello, my name is "<< getName() << ", I am " << getAge()<<" years old." << endl;
    }
    
    int main()
    {
        Person p1;
        Person p2("Jack Wilson",40);
        p1.Introduce();
        p2.Introduce();
    }
    Changes:
    - Added prefix m_ to member variables to distinguish them from local variables.
    - Added names of parameters to member functions and constructors.
    - Used initializer list instead of assignment in constructors.
    - Changed Introduce to a non-static member function.
    - Added const correctness.
    - Added setters.
    - Changed code in main to reflect changes in class.

    Setters can be good or bad. You should reflect on whether you want the creator to be able to change the contents of the class after it's created.
    Code may contain some errors.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by dhuan
    i still wanna leave that "Introduce" function as static, so i can can call it directly from the class.
    I don't understand your reasoning here. What do you mean by "call it directly from the class"?

    Quote Originally Posted by Elysia
    - Added prefix m_ to member variables to distinguish them from local variables.
    Note that this is a matter of subjective style. Not decorating member variables in this way (or any other way) is fine.

    Quote Originally Posted by Elysia
    - Changed Introduce to a non-static member function.
    Note that this is not an improvement: the member function still has access to the internals of the class when it could have done with just the public interface.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by laserlight View Post
    Note that this is not an improvement: the member function still has access to the internals of the class when it could have done with just the public interface.
    It makes more sense to have it non-static, and that is all I wanted to show.
    Making it a non-class member might be more wise, still. But you already mentioned that.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Classes and constructors help please
    By S_Diggy in forum C++ Programming
    Replies: 7
    Last Post: 08-27-2007, 12:03 PM
  2. classes and overloading constructors
    By barneygumble742 in forum C++ Programming
    Replies: 2
    Last Post: 09-14-2005, 05:32 AM
  3. constructors in classes
    By Kenman in forum C++ Programming
    Replies: 16
    Last Post: 07-28-2003, 07:35 AM
  4. Classes: constructors, destructors ???
    By mbeisser21 in forum C++ Programming
    Replies: 18
    Last Post: 07-21-2002, 09:33 PM
  5. Replies: 2
    Last Post: 01-15-2002, 06:00 PM