【问题标题】:No matching function for call to ‘student::student()’ error [duplicate]没有匹配函数调用‘student::student()’错误[重复]
【发布时间】:2023-03-23 17:15:01
【问题描述】:

以下代码在继承方面有什么问题?出现no matching function for call to ‘student::student()’ 错误。

class student {
 private:
  string firstname;
  string lastname;

 public:
  student(string fname, string lname) {
    firstname = fname;
    lastname = lname;
  }
  string getname() { return firstname + lastname; }
  void setfirstname(string fname) { this->firstname = fname; }
};

class undergraduate : public student {
 private:
  double gpa;
  student* stu;

 public:
  undergraduate(string firstname, string lastname, double gpa) {
    stu = new student(firstname, lastname);
    this->gpa = gpa;
  }
};

int main() {
  undergraduate stu1("Sam", "Singh", 4.0);
  stu1.setfirstname("temp");
  cout << stu1.getname();
}

请指出错误并帮助我纠正它。谢谢!

【问题讨论】:

  • 您应该像这样称呼学生 ctor:undergraduate(string firstname, string lastname, double gpa) : student(firstname, lastname), gpa(gpa) { } 并失去 student* stu; 似乎您不了解继承。
  • 基类构造函数总是在派生类构造函数中调用。每当您创建派生类对象时。由于您没有默认 ctor,Johnny 的评论说明了如何使用 2 个参数调用您的 ctor。
  • @JohnnyMopp 我正在学习。
  • 我的意思不是侮辱。但也许你应该回去重新阅读关于继承的章节。另见:What are the rules for calling the base class constructor?
  • @JohnnyMopp 我从未感到受到侮辱。我只是说我正在学习,详细的答案对我的帮助不仅仅是捷径!

标签: c++ oop inheritance


【解决方案1】:

看起来你可能是一名 Python 程序员,所以这是你的代码,用该语言重写

class student:
    def __init__(self, fname, lname):
        self.firstname = fname;
        self.lastname = lname;

    @property
    def name(self):
        return self.firstname + self.lastname

class undergraduate(student):
    def __init__(self, fname, lname, gpa):
        super().__init__(fname, lname)
        self.gpa = gpa
 
stu1 = undergraduate("Sam", "Singh", 4.0);
stu1.firstname = "temp";
print(stu1.name)

首先要注意的是undergraduate 不包含student 成员。因为它继承自student是一个),所以不需要undergraduate 中的成员。 C++ 类也是如此。

但是,在 Python 代码中,undergraduate 类在 undergraduate ctor 的主体中调用 student ctor。这与它在 C++ 中的工作方式不同。该语言使用“初始化列表”。这些不仅用于调用父ctor,还用于初始化成员变量。

class student {
 private:   // You may want to change to protected so child classes can access
  string firstname;
  string lastname;

 public:
  student(string fname, string lname) {
    firstname = fname;
    lastname = lname;
  }
  string getname() { return firstname + lastname; }
  void setfirstname(string fname) { this->firstname = fname; }
};

class undergraduate : public student {
 private:
  double gpa;
 
 public:
  undergraduate(string firstname, string lastname, double gpa) :
    student(firstname, lastname),  // Call parent ctor
    gpa(gpa)                       // Initialize this->gpa to gpa parameter
  {
      // The initializer list has taken care of everything so there's nothing here
      // But additional code could be added if needed.
  }
};

int main() {
  undergraduate stu1("Sam", "Singh", 4.0);
  stu1.setfirstname("temp");
  cout << stu1.getname();
}

如果您对继承的工作原理感到困惑,我强烈建议您找一本好书或教程。关于 SO 的答案无法详细说明这些概念。
The Definitive C++ Book Guide and List
Constructors and member initializer lists


RE 代码中的原始错误:编译器正在寻找 student 的默认 ctor(无参数),但您没有提供。见:When do we need to have a default constructor?

【讨论】:

  • OP 从未要求过 Python 代码翻译;因此答案部分是多余的。
  • @Const 我认为您的意思是“不必要的”而不是“冗余的”。但我不同意:它是以 OP 可能熟悉的形式展示这个概念的。
  • @Const,我是一名 Python 程序员。因此,通过将其与我的思维方式联系起来来解释我的疑问是一种我非常喜欢的神秘艺术。答案中没有多余的东西。
【解决方案2】:

undergraduate 是一个 student。所以undergraduate的构造需要先构造父类student

由于你没有提供,如何构造父student

 undergraduate(string firstname, string lastname, double gpa) 
 {
    stu = new student(firstname, lastname);
    this->gpa = gpa;
 }

在涉及到构造函数体之前,编译器会尝试通过调用student 的默认构造函数来为你做这件事。由于学生有参数化构造函数student(string fname, string lname),编译器不会为你生成一个,最终没有学生的默认构造函数。这会导致错误。

其次,您不需要指向父级的指针,除非您有任何其他特殊要求。

因此,您有两种不同的选择来解决问题。

  1. student 提供默认构造函数。
  2. 或者在子构造函数(undergraduate)中初始化student,去掉指向student的冗余指针。

也可以使用constructor member initializer list 来初始化类的成员:

undergraduate(string firstname, string lastname, double gpa)
 :  student{ std::move(firstname), std::move(lastname)}
 ,  gpa{ gpa} 
 {}

【讨论】:

  • 初始化列表中的gpa{ gpa} 可以使用一些解释。对于初学者来说,它的实际作用并不明显。
猜你喜欢
  • 2017-03-27
  • 2016-04-19
  • 2019-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-02
  • 2013-05-05
  • 2011-08-27
相关资源
最近更新 更多