[英]c++ derived constructor when defining function outside of class body - "no default constructor"
我正在通过 Bjarne Stroustrup 的编程原理书独自工作,并且在定义构造函数时遇到了麻烦。 这个问题需要使用一个从 FLTK 图形库构建的接口; 一般不用担心。 我们必须用圆类制作一个笑脸,它没有默认构造函数——常规构造函数接受一个 (x,y) 点和一个半径。 我希望能够进行一些计算/做其他事情 - 所以试图在类主体之外为我的笑脸定义构造函数。 这不起作用,并且我不断收到错误(来自 Visual Studio)“类“Graph_lib::Circle”不存在默认构造函数。
struct Smiley :public Circle {
Smiley(Point p, int rr);
void draw_lines() const;
void sc(Color c);
Circle l_eye;
Circle r_eye;
};
Smiley::Smiley(Point p, int rr) {
Circle(p, rr);
Circle l_eye(Point(p.x - 50, p.y - 50), rr / 8);
Circle r_eye(Point(p.x + 50, p.y - 50), rr / 8);
}
基本上,上述方法不起作用。 我认为它出于某种原因试图以某种方式创建一个默认 Circle,但是找不到它的默认功能(因为我没有写过),然后抛出错误。 我已经为这个函数尝试了大量不同的组合,但似乎无法让它不尝试和罚款默认值。 请注意,如果我在 Smiley::Smiley 中去掉 l_eye 和 r_eye 之前的“Circle”类型 - 它仍然会抛出“调用类类型的对象而没有适当的 operator() 或转换函数指向指针的错误” -功能类型”。
但是,如果我只是在初始化列表中定义它,它就可以正常工作。
struct Smiley :public Circle {
Smiley(Point p, int rr) : Circle(p, rr), l_eye(Point(p.x - 50, p.y - 50), rr/8), r_eye(Point(p.x + 50, p.y - 50), rr/8) {}
void draw_lines() const;
void sc(Color c);
Circle l_eye;
Circle r_eye;
};
显然,这是一个非常简单的例子。 但是,我认为获得它对我来说很重要,因为将来会有很多时候我需要在外部构造函数中实际进行计算。 如果有人可以帮助解释问题所在,那就太好了。
该声明
Circle(p, rr);
创建一个不使用的临时Circle
对象。
然后
Circle l_eye(Point(p.x - 50, p.y - 50), rr / 8);
Circle r_eye(Point(p.x + 50, p.y - 50), rr / 8);
正在创建两个新的对象和变量,与您的同名成员变量完全无关。
你得到的错误是因为编译器需要初始化(构造)基类和成员变量l_eye
和r_eye
,作为Smiley
构造的一部分,并且这个初始化是在调用Smiley
构造函数体之前完成的。
在某种程度上,您的构造函数:
Smiley::Smiley(Point p, int rr) {
Circle(p, rr);
Circle l_eye(Point(p.x - 50, p.y - 50), rr / 8);
Circle r_eye(Point(p.x + 50, p.y - 50), rr / 8);
}
相当于:
Smiley::Smiley(Point p, int rr)
: Circle(), l_eye(), r_eye() // Default initialization
{
Circle(p, rr);
Circle l_eye(Point(p.x - 50, p.y - 50), rr / 8);
Circle r_eye(Point(p.x + 50, p.y - 50), rr / 8);
}
如果Circle
没有默认构造函数(它似乎没有,否则你不会得到关于它的错误),那么这根本不可能。
您可以在您的类外定义构造函数中编写初始化列表,就像您在类内定义构造函数中所做的那样。
如果我只是在初始化列表中定义它,它工作正常。
所以这样做。 这就是你应该做的。 初始化列表正是为此而存在的。
未来会有很多次
在外部构造函数中进行计算。
在紧要关头,您可以编写一个辅助函数并从中复制初始化您的基类子对象:
Circle enormouslyComplicatedAuxiliaryFunction(Point p, int rr);
Smiley(Point p, int rr) : Circle(enormouslyComplicatedAuxiliaryFunction(p, rr)) { ... }
但是,如果您发现自己经常这样做,请考虑重新设计Circle
。 施工是为了简单。 如果你需要计算很多东西来创建你的基类对象,那么你可能应该有一个专用于计算这些东西的基类构造函数。
(但是等等,如果Circle
是抽象的呢?好吧,如果你需要很多东西来初始化一个抽象类 subobject ,它的设计几乎肯定会被破坏。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.