子类构造函数

Subclass Constructors

本文关键字:构造函数 子类      更新时间:2023-10-16

我在C++中处理子类时遇到问题。我有一个多边形的类和一个三角形的子类。我希望能够通过传递点*(这是一个自定义类)的向量来声明多边形,通过传递三个点*s来声明三角形。

我的理解是Triangle类构造函数应该调用Polygon类的构造函数。

这就是我目前所拥有的:

class Polygon
{
public:
    vector<Point*> pts;
    Polygon(vector<Point*> aPts) : pts(aPts) {};
};
class Triangle : public Polygon
{
public:
    Triangle(Point* A, Point* B, Point* C) 
    {
        vector<Point*> APts;
        APts.push_back(A); APts.push_back(B); APts.push_back(C);
        Polygon(APts);
    }
};

然而,在三角形构造函数的左括号上,我得到了错误:

error: no matching function call to 'Polygon::Polygon()'

有人能帮忙吗?

基类必须在派生类的构造函数主体之前初始化;如果构造函数需要参数,则必须在初始化程序列表中提供这些参数:

Triangle(Point* A, Point* B, Point* C) :
    Polygon({A,B,C})
{}

请注意,这使用C++11语法来创建临时向量;如果你被困在过去,那就有点复杂了:

static std::vector<Point*> make_points(Point* A, Point* B, Point* C) {
    std::vector<Point*> points;
    points.push_back(A);
    points.push_back(B);
    points.push_back(C);
}
Triangle(Point* A, Point* B, Point* C) :
    Polygon(make_points(A,B,C))
{}

或者,给基类一个默认构造函数,然后在派生类构造函数中填充向量可能更容易(但可能更容易出错):

// In Polygon
Polygon() {} // constructed with no points
// pts must be "public" or "protected"
// In Triangle
Triangle(Point* A, Point* B, Point* C) {
    pts.push_back(A);
    pts.push_back(B);
    pts.push_back(C);
}

您可以在Polygon类中拥有addPoint()函数

class Polygon{
  public:
    vector<Point*> pts;
    Polygon(){}/// < The default constructor
    Polygon(vector<Point*> aPts) : pts(aPts) {}
    void addPoint(Point* p){
        pts.push_back(p);
    }
};
class Triangle : public Polygon{
public:
    Triangle(Point* A, Point* B, Point* C){// calls the default constructor
        addPoint(A);
        addPoint(B);
        addPoint(C);
    }
};

此外,Point在大多数情况下都可以通过值进行复制。我不知道你们为什么用指针传过去。

它试图调用Polygon类的默认构造函数,但由于您有自己的构造函数,默认的空构造函数已不存在。因此,您必须使用正确的参数调用Polygon's构造函数,或者定义一个空的构造函数。

另外,不能用这样的参数来创建Polygon's构造函数,这必须在Triangle类构造函数的初始化列表中完成。这样做是为了确保在创建derived类对象之前正确初始化base的成员。

Polygon类中,定义一个采用参数vector的构造函数。在这种情况下,编译器不会生成默认构造函数,因此必须Polygon构造函数传递参数。

Triangle中,您定义了一个使用三个参数的构造函数,但不调用Polygon的构造函数。编译器试图找到一个默认构造函数——一个没有参数的构造函数——但找不到,因此会发出错误。

不能像您所写的那样在Triangle构造函数的末尾调用Polygon构造函数。Polygon ctor必须在`Triangle ctor之前执行。

尝试在Polygon中添加一个直接获取三个Point的ctor,而不是在vector中,如以下

class Polygon
{
public:
    vector<Point*> pts;
    Polygon(Point* A, Point* B, Point* C) {
        pts.push_back(A);
        pts.push_back(B);
        pts.push_back(C);
    }
};
class Triangle : public Polygon
{
public:
    Triangle(Point* A, Point* B, Point* C) : Polygon(A, B, C)
    {
    }
};

您必须调用Polygon构造函数作为初始化器列表的一部分,这意味着您需要构建一个初始化向量的函数;

class Triangle : public Polygon
{
    // static method, not part of the object being constructed.
    static vector<Point*> BuildVector(Point* A, Point* B, Point* C) {
        vector<Point*> APts;
        APts.push_back(A); APts.push_back(B); APts.push_back(C);
        return APts;
    }
public:
    // Need to call Polygon's constructor before even entering our own;
    Triangle(Point* A, Point* B, Point* C) : Polygon(BuildVector(A, B, C))
    {
    }
};

请注意,在不复制对象的情况下将指针推入向量,可能会导致内存处理不正确(谁来释放内存?),因此您可能希望使用某种类型的智能指针,或者只是将点作为引用传递到构造函数中。

基类的构造函数应该从子类的构造函数的初始值设定项列表中调用。这就是导致代码中出现编译器错误的原因。下面的语法也是有效的,但它只是创建一个Polygon的临时对象并将其卸载:
Polygon(APts);

从设计的角度来看,通过按值复制矢量,您正在进行昂贵的操作
只是不要这么做。有一个无参数的构造函数,然后再填充构造函数。

class Polygon
{
public:
    vector<Point*> pts;  // can be made protected as well
    Polygon() {};
};
class Triangle : public Polygon
{
public:
    Triangle(Point* A, Point* B, Point* C) 
    {
        pts.push_back(A); pts.push_back(B); pts.push_back(C);
    }
};

如果您支持C++11,那么可以更优雅地编写相同的代码。

class Polygon {
protected:
  vector<Point*> pts; 
public:
  Polygon(std::initializer_list<Point*>& v) : pts(v) {}
};
class Triangle : public Polygon {
public:
  Triangle (Point* p1, Point* p2, Point* p3) :
  Polygon({p1, p2, p3}) {}
};
class Square : public Polygon {
public:
  Square (Point* p1, Point* p2, Point* p3, Point* p4) :
  Polygon({p1, p2, p3, p4}) {}
};

用法:

Triangle t({x, y, z});
Square s({w, x, y, z});