我在使用C ++中的子类时遇到问题。我有一个Polygon的类和一个Triangle的子类。我希望能够通过传递一个Point *(这是一个自定义类)的矢量和一个Triangle传递三个Point *来声明一个Polygon。
我的理解是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);
}
};
但是,在Triangle构造函数的左括号中我收到错误:
error: no matching function call to 'Polygon::Polygon()'
有人可以帮忙吗?
答案 0 :(得分:4)
必须在派生类的构造函数体之前初始化基类;如果构造函数需要参数,则必须在初始化列表中提供这些参数:
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);
}
答案 1 :(得分:2)
您可以在addPoint()
班级
Polygon
功能
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
可以按值进行复制。我不知道你为什么用指针传递它。
答案 2 :(得分:1)
它试图调用Polygon
类的默认构造函数,但由于你有自己的构造函数,因此默认的空构造函数不再存在。因此,您必须使用适当的参数调用Polygon's
构造函数或定义一个空构造函数。
此外,您可以使用类似参数的Polygon's
构造函数,这必须在Triangle
类构造函数的初始化列表中完成。这样做是为了确保在创建base
类对象之前正确初始化derived
的成员。
答案 3 :(得分:1)
在Polygon
类中,定义一个带参数的构造函数vector
。在这种情况下,编译器不会生成默认构造函数,因此 可以为Polygon
构造函数传递参数。
在Triangle
中,您定义了一个带有三个参数的构造函数,但是您没有调用Polygon
的构造函数。编译器尝试查找默认构造函数 - 一个没有参数的构造函数 - 但找不到一个,因此发出错误。
您无法像编写的那样在Polygon
构造函数的末尾调用Triangle
构造函数。 Polygon
ctor必须在`Triangle ctor。
尝试将ctor添加到Polygon
,直接取代Point
而不是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)
{
}
};
答案 4 :(得分:1)
应该从子类的构造函数的初始化列表中调用基类的构造函数。这就是导致代码中编译器错误的原因。下面的语法也是有效的,但它只是创建了一个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});
答案 5 :(得分:1)
您必须将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))
{
}
};
请注意,通过将指针推入向量而不复制对象,您可能无法正确处理内存(谁将释放内存?),因此您可能希望使用某种类型的smart pointer,或者只是将点作为引用传递给构造函数。