涉及派生类成员函数
Posted
技术标签:
【中文标题】涉及派生类成员函数【英文标题】:Derived class member functions are involved 【发布时间】:2020-08-08 07:04:34 【问题描述】:我从C++ Templates the Complete Guide
书中得到了一段代码:
在下面的程序中,我们创建了一个带有完美转发模板构造函数的Person
类
和另外两个成员函数(const拷贝构造函数,移动构造函数)
#include <utility>
#include <string>
#include <iostream>
class Person
private:
std::string name;
public:
// generic constructor for passed initial name:
template<typename STR>
explicit Person(STR&& n) : name(std::forward<STR>(n))
std::cout << "TMPL-CONSTR for '" << name << "'\n";
// copy and move constructor:
Person (Person& p) : name(p.name)
std::cout << "COPY-CONSTR Person '" << name << "'\n";
Person (Person const& p) : name(p.name)
std::cout << "COPY-CONSTR Person '" << name << "'\n";
Person (Person&& p) : name(std::move(p.name))
std::cout << "MOVE-CONSTR Person '" << name << "'\n";
;
int main()
std::string s = "sname";
Person p1(s);
Person p2("tmp");
Person p3(p1); // Error
Person p4(std::move(p1));
关于Person p3(p1);
行的错误,这本书说“根据重载解决规则”
template<typename STR>
Person(STR&& n)
“比复制构造更好匹配”
Person(const Person& p)
所以,如果我在 Person 内部再添加一个构造函数,如下所示:
Person (Person& p) : name(p.name)
std::cout << "COPY-CONSTR Person '" << name << "'\n";
错误应该消失。确实错误消失了,这是输出:
TMPL-CONSTR for 'sname'
TMPL-CONSTR for 'tmp'
COPY-CONSTR Person 'sname' : this is due to `Person (Person& p)`
MOVE-CONSTR Person 'sname'
但书上也说,这只是部分解决方案,因为 Person 的 Derived 类的模板构造函数仍然是重载决议规则的更好匹配。
所以我也试着检查一下:
#include <utility>
#include <string>
#include <iostream>
class Person
private:
std::string name;
public:
// generic constructor for passed initial name:
template<typename STR>
explicit Person(STR&& n) : name(std::forward<STR>(n))
std::cout << "TMPL-CONSTR for '" << name << "'\n";
// copy and move constructor:
Person (Person& p) : name(p.name)
std::cout << "COPY-CONSTR Person '" << name << "'\n";
Person (Person const& p) : name(p.name)
std::cout << "COPY-CONSTR Person '" << name << "'\n";
Person (Person&& p) : name(std::move(p.name))
std::cout << "MOVE-CONSTR Person '" << name << "'\n";
;
#if 1 // or 0
class newPerson : public Person
private:
std::string name;
public:
// generic constructor for passed initial name:
template<typename STR>
explicit newPerson(STR&& n) : name(std::forward<STR>(n))
std::cout << "TMPL-CONSTR for '" << name << "'\n";
// copy and move constructor:
newPerson (newPerson const& p) : name(p.name)
std::cout << "COPY-CONSTR Person '" << name << "'\n";
newPerson (newPerson&& p) : name(std::move(p.name))
std::cout << "MOVE-CONSTR Person '" << name << "'\n";
;
#endif
int main()
std::string s = "sname";
Person p1(s);
Person p2("tmp");
Person p3(p1); // Error again
Person p4(std::move(p1));
在这种情况下我正在粘贴 clang 错误(gcc 错误列表太大)
specialmemtmplMain.cpp:41:5: error: constructor for 'newPerson' must explicitly initialize the base class 'Person' which does not have a default constructor
newPerson (newPerson const& p) : name(p.name)
^
specialmemtmplMain.cpp:5:7: note: 'Person' declared here
class Person
^
specialmemtmplMain.cpp:44:5: error: constructor for 'newPerson' must explicitly initialize the base class 'Person' which does not have a default constructor
newPerson (newPerson&& p) : name(std::move(p.name))
^
specialmemtmplMain.cpp:5:7: note: 'Person' declared here
class Person
^
2 errors generated.
所以,我的问题是,我没有实例化任何 newPerson
类。那为什么错误是指newPerson
构造函数?这里到底发生了什么?
【问题讨论】:
【参考方案1】:问题是派生类应该调用基类的构造函数之一。你没有显式调用构造函数,所以编译器会尝试隐式调用Person::Person()
的默认构造函数,但是没有定义默认构造函数。
【讨论】:
以上是关于涉及派生类成员函数的主要内容,如果未能解决你的问题,请参考以下文章