模板函数忽略继承 class 的成员
Template function ignores members from inherited class
我正在尝试编写一个程序来比较一些形状的面积,形状是基础 class。
该程序还有 2 个其他 class 派生自形状 class.
我是这样定义它们的:
class Shape
{
protected:
string color;
public:
Shape();
Shape(string);
virtual double Perimeter();
virtual void printMe();
virtual double Area();
};
class Square:
public Shape
{
int x, y;
double side;
public:
Square();
Square(string, int, int, double);
double Perimeter();
void printMe();
double Area();
};
class Circle:
public Shape
{
int x, y, radius;
public:
Circle();
Circle(string, int, int, int);
double Perimeter();
void printMe();
double Area();
};
在 main 中,我创建了以下对象:
Shape f1, f2("green");
Circle c1, c2("green", 2, 2, 2);
Square p1, p2("blue", 0, 0, 5);
Shape* f3 = &c1;
Shape* f4 = &c2;
Shape* f5 = new Square("blue", 1, 0, 2);
Shape* f6 = &p2;
我想构建一个函数,它接受任何 Shape 对象和 return 具有最大面积的对象。
我这样试过:
template <typename T>
T maxim(initializer_list<T> list) {
T maxx;
for (auto i : list)
{
if (i.Area() > maxx.Area())
maxx = i;
}
return maxx;
}
在 main 中,我尝试调用函数:
maxim<Shape>({*f3, *f4, *f5, *f6}).printMe();
程序没有任何错误,只显示一个空字符串(因为 maxx
是一个用空字符串初始化的 Shape
)。
对象f3
、f4
、f5
和f6
在我调用printMe()
方法时就显示出来了,所以我想当我调用 maxim
函数,只有成员 color
被分配给对象。没有 x
、y
、side
或 radius
成员分配给他们。
我认为问题在于对象只是 Shapes
并且它们只有 color
成员。
有什么方法可以将列表中的对象解释为 Cricles 和 Squares,以便我可以使用 Area()
方法比较它们?
您正在尝试在此处使用多态性。不幸的是,C++ 中的多态性适用于指针或引用,但不适用于普通对象,因为 slicing(感谢 @Jarod42 提供该参考)。
并且由于无法将引用分配给(而是分配给引用对象),因此您不能在容器中使用它们 也不能在初始化列表中使用 .
这意味着您将不得不在 maxim
:
中使用好的旧指针
template <typename T>
T* maxim(initializer_list<T*> list) {
T* maxx = nullptr;
for (auto i : list)
{
if (nullptr == maxx || i->Area() > maxx->Area())
maxx = i;
}
return maxx;
}
从那时起,您将能够做到:
maxim<Shape>({f3, f4, f5, f6})->printMe();
我正在尝试编写一个程序来比较一些形状的面积,形状是基础 class。 该程序还有 2 个其他 class 派生自形状 class.
我是这样定义它们的:
class Shape
{
protected:
string color;
public:
Shape();
Shape(string);
virtual double Perimeter();
virtual void printMe();
virtual double Area();
};
class Square:
public Shape
{
int x, y;
double side;
public:
Square();
Square(string, int, int, double);
double Perimeter();
void printMe();
double Area();
};
class Circle:
public Shape
{
int x, y, radius;
public:
Circle();
Circle(string, int, int, int);
double Perimeter();
void printMe();
double Area();
};
在 main 中,我创建了以下对象:
Shape f1, f2("green");
Circle c1, c2("green", 2, 2, 2);
Square p1, p2("blue", 0, 0, 5);
Shape* f3 = &c1;
Shape* f4 = &c2;
Shape* f5 = new Square("blue", 1, 0, 2);
Shape* f6 = &p2;
我想构建一个函数,它接受任何 Shape 对象和 return 具有最大面积的对象。 我这样试过:
template <typename T>
T maxim(initializer_list<T> list) {
T maxx;
for (auto i : list)
{
if (i.Area() > maxx.Area())
maxx = i;
}
return maxx;
}
在 main 中,我尝试调用函数:
maxim<Shape>({*f3, *f4, *f5, *f6}).printMe();
程序没有任何错误,只显示一个空字符串(因为 maxx
是一个用空字符串初始化的 Shape
)。
对象f3
、f4
、f5
和f6
在我调用printMe()
方法时就显示出来了,所以我想当我调用 maxim
函数,只有成员 color
被分配给对象。没有 x
、y
、side
或 radius
成员分配给他们。
我认为问题在于对象只是 Shapes
并且它们只有 color
成员。
有什么方法可以将列表中的对象解释为 Cricles 和 Squares,以便我可以使用 Area()
方法比较它们?
您正在尝试在此处使用多态性。不幸的是,C++ 中的多态性适用于指针或引用,但不适用于普通对象,因为 slicing(感谢 @Jarod42 提供该参考)。
并且由于无法将引用分配给(而是分配给引用对象),因此您不能在容器中使用它们 也不能在初始化列表中使用 .
这意味着您将不得不在 maxim
:
template <typename T>
T* maxim(initializer_list<T*> list) {
T* maxx = nullptr;
for (auto i : list)
{
if (nullptr == maxx || i->Area() > maxx->Area())
maxx = i;
}
return maxx;
}
从那时起,您将能够做到:
maxim<Shape>({f3, f4, f5, f6})->printMe();