简体   繁体   中英

C++ code -calling a constructor of one class within a constructor of same class

I am trying to compile this C++ code unfortunately, I failed to compile the code below. Can you help me by explaining why I am getting this error?

#include <iostream>
#include <cstring>
using namespace std;

class student
{
   private:
    char name[10];
    int id;
    int fee;
       public:
           student(char name[10],int id)
           {
               strcpy(this->name,name);  //string copy
               this->id=id;
               fee=0;
           }
           student(char name[10],int id,int fee)
           {
               student::student(name,id); //calling a constructor of one class 
                                         // within a constructor of same class
               this->fee=fee;
           }
           void show() //print function
           {
               cout<<"Name:"<<name<<endl;
               cout<<"id:"<<id<<endl;
               cout<<"fee:"<<fee<<endl<<endl;
           }
};

int main()
{
 student s1("DAVID",123);
 student s2("WILLIAM",124,5000);
 s1.show();
 s2.show();

    return 0;
}

Below is the error GCC is complaining about.: main.cpp|20|error: cannot call constructor 'student::student' directly [-fpermissive]|

As rightly suggested by @sweenish, You must do the constructor delegation in the initialization section. Something like this:

#include <iostream>
#include <cstring>
using namespace std;

class student
{
   private:
    char name[10];
    int id;
    int fee;
       public:
           student(char name[10],int id)
           {
               strcpy(this->name,name);  //string copy
               this->id=id;
               fee=0;
           }
           student(char name[10],int id,int fee): student(name, id) // constructor delegation
           {
               this->fee=fee;
           }
           void show() //print function
           {
               cout<<"Name:"<<name<<endl;
               cout<<"id:"<<id<<endl;
               cout<<"fee:"<<fee<<endl<<endl;
           }
};

int main()
{
 student s1("DAVID",123);
 student s2("WILLIAM",124,5000);
 s1.show();
 s2.show();

    return 0;
}

Also, an advice for you. You may define the more specialized constructor and delegate the responsibility of less specialized constructors to more specialized ones.

#include <iostream>
#include <cstring>
using namespace std;

class student
{
   private:
    char name[10];
    int id;
    int fee;
       public:
           student(char name[10],int id, int fee): id{id}, fee{fee} // more specialized
           {
               strcpy(this->name,name);  //string copy
           }
           student(char name[10],int id): student(name, id, 0) { } // less specialized calling the more specialized constructor
           void show() //print function
           {
               cout<<"Name:"<<name<<endl;
               cout<<"id:"<<id<<endl;
               cout<<"fee:"<<fee<<endl<<endl;
           }
};

int main()
{
 student s1("DAVID",123);
 student s2("WILLIAM",124,5000);
 s1.show();
 s2.show();

    return 0;
}

Here's your code with changes made to get it compiling; I marked the changes with comments.

#include <iostream>
// #include <cstring>  // CHANGED: Prefer C++ ways when writing C++
#include <string>  // CHANGED: The C++ way
// using namespace std;  // CHANGED: Bad practice

class student {
 private:
  std::string name{};  // CHANGED: Move from C-string to std::string
  int id = 0;          // CHANGED: Default member initialization
  int fee = 0;

 public:
  // CHANGED: Move from C-string to std::string
  student(std::string name, int id)
      : name(name),
        id(id)
  // CHANGED: ^^ Utilize initialization section
  {
    // CHANGED: Not needed anymore
    //  strcpy(this->name,name);  //string copy
    //  this->id=id;
    //  fee=0;
  }

  student(std::string name, int id, int fee) : student(name, id) {
    // CHANGED: Not needed anymore
    //  student::student(name,id); //calling a constructor of one class
    //                            // within a constructor of same class
    // NOTE: Inconsistency with other ctor w.r.t. this->
    this->fee = fee;
  }

  void show()  // print function
  {
    std::cout << "Name:" << name << '\n';
    std::cout << "id:" << id << '\n';
    std::cout << "fee:" << fee << "\n\n";
  }
};

int main() {
  student s1("DAVID", 123);
  student s2("WILLIAM", 124, 5000);
  s1.show();
  s2.show();

  return 0;
}

Here is the same code, but with the stuff I commented out removed to make it easier to read.

#include <iostream>
#include <string>

class student {
 private:
  std::string name{};
  int id = 0;
  int fee = 0;

 public:
  student(std::string name, int id) : name(name), id(id) {}

  student(std::string name, int id, int fee) : student(name, id) {
    this->fee = fee;
  }

  void show()
  {
    std::cout << "Name:" << name << '\n';
    std::cout << "id:" << id << '\n';
    std::cout << "fee:" << fee << "\n\n";
  }
};

int main() {
  student s1("DAVID", 123);
  student s2("WILLIAM", 124, 5000);
  s1.show();
  s2.show();

  return 0;
}

The initialization section follows the parameter list and is marked with : . You then initialize each member, in the order they are declared .

In the case of the constructor doing the delegating, you are unable to initialize fee in the initialization section. The error I receive is a delegating constructor cannot have other mem-initializers .

I don't like splitting my initialization like that, and if you insist on delegating constructor calls for this class, implement the most specific constructor and delegate to it with your less specific constructors. I prefer default member initialization as I think it leads to less confusion and written code overall.

The code then compiles and you get the expected output:

Name:DAVID
id:123
fee:0

Name:WILLIAM
id:124
fee:5000

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