繁体   English   中英

c++ 在类体之外定义函数时派生的构造函数 - “无默认构造函数”

[英]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_eyer_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.

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