简体   繁体   中英

C++ Basic Class Constructor

I'm going through a C++ course right now, and they're doing a good job of over-explaining everything until it comes to splitting the files up between header "promises" and implementation. I learned programming entirely in Python so I'm used to just declaring things outright and importing the class as necessary, so this whole separating a promise and then implementing logic is strange to me.

Anyway, I'm having trouble because in the course they were saying you never actually need to use this-> but when I'm trying to define a class explicitly in the same .cpp file, I can only get the constructor to work when I use this-> . Can someone please explain or link a discussion that explains this? I haven't been able to find a reference that explains this issue in the context of defining everything in the same file.

class Person {
    public:
    string name;
    int age;
    int height;
    int weight;
    Person (string name, int age, int height, int weight) {
        name = name;
        age = age;
        height = height;
        weight = weight;
    }   
};

int main () {
    Person new_person("Doug", 20, 70, 170);
}

This causes all the values I pass in from the main function to not initialize. However, if I add this-> to each line in the constructor, it works fine. The examples I find don't use this-> so I'm confused why it's necessary here. Perhaps it has to do with namespaces which are still a little confusing to me (the whole using namespace std; thing) but I thought since it's all in the same .cpp file, this should work.

The argument variables overshadow your member variables in the scope of your constructor. That is, within that context, name refers to the input variable only.

What you could do is use an initialization list:

Person (string name, int age, int height, int weight) :
    name(name), age(age), height(height), weight(weight) {}

Or use different names:

Person (string _name, int _age, int _height, int _weight) {
    name = _name;
    age = _age;
    height = _height;
    weight = _weight;
}   

But your approach using this-> is totally fine.

You might also want to read http://www.cs.technion.ac.il/users/yechiel/c++-faq/using-this-in-ctors.html

In this case you need this because you are using the same name for both your constructor parameters and class members.

Person (string name, int age, int height, int weight) {
    this->name = // this-> means the member variable
        name;    // just the parameter

If you had a different name for your parameter this would not be necessary

Person (string name_, int age, int height, int weight) {
    name =      // the member variable
        name_;  // the parameter

Only problem with ->this approach is that it is A) wordy b) doesn't initialize object. c) makes this object non-trivial.

Proper initializing constructor would look like this, using initialization list:

Person (string nm, int ag, int ht, int wt): 
    name(nm), age(ag), height(ht), weight(wt) {}

It's not really same as doing what you do, in this case object can be created statically without performing any actions. Your implementation of class always performs assignments. C++11 and later allows to do away with fully trivial implementation:

class Person {
    public:
    string name;
    int age;
    int height;
    int weight;

    void do_stuff() {};
};

// let's assume that string is std::string, 
// creation from  const char* and = are defined
int main()
{
  Person p = { "Nemo", 35, 5, 120 };
  Person p2 = p;
  p = { "John-117", 24, 6, 170 };
}

What you have is a case of ambiguity of dependent names . See here :

If the lookup of a member of current instantiation gives a different result between the point of instantiation and the point of definition, the lookup is ambiguous. Note however that when a member name is used, it is not automatically converted to a class member access expression, only explicit member access expressions indicate members of current instantiation:

Eli Bendersky writes eloquently about this. An excerpt:

All you have to do is to make the compiler understand that the call f depends on the template parameter T. A couple of ways to do this are replacing f() with Base::f() , or with this->f() (since this is implicitly dependent on T).

So your own this-> solution is more than fine : )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM