如何使 C++ 中的孙子可以覆盖 super class 的虚函数?
How to make virtual functions of a super class overrideable for grandchildren in C++?
大家好,这是我要使用的一些代码 运行,问题是它无法按照我的预期运行。我无法弄清楚它有什么问题。我是c++菜鸟,请帮忙。
#include <iostream>
#include <cmath>
#include <stdexcept>
using namespace std;
/**
* Super class
*/
class Shape
{
protected:
int _dimensions;
public:
Shape() : _dimensions{0}
{};
Shape(int dims) : _dimensions{dims}
{};
virtual double getArea() {};
// Because some shapes have no volume.
virtual double getVolume() {};
void setDimensions(int dim)
{
this->_dimensions = dim;
};
int getDimensions()
{
return this->_dimensions;
};
};
/**
* Extended classes
*/
class TwoDimensionalShape : public Shape
{
public:
TwoDimensionalShape() : Shape{2}
{};
// This should throw an error
double getVolume() {
throw logic_error("This shape ain't got area!");
};
};
class ThreeDimensionalShape : public Shape
{
public:
ThreeDimensionalShape() : Shape{3} {};
};
/**
* Final Concrete classes extending extended classes
*/
class Circle : public TwoDimensionalShape
{
protected:
double _radius;
public:
Circle(double r) : _radius{r}
{};
double getArea()
{
// pi*r^2
return M_PI * pow(_radius, 2);
}
};
class Square : public TwoDimensionalShape
{
protected:
double _side;
public:
Square(double s) : _side{s}
{}
double getArea()
{
// s^2
return pow(_side, 2);
}
};
class Triangle : public TwoDimensionalShape
{
protected:
double _base, _height;
public:
Triangle(double b, double h) : _base{b}, _height{h}
{};
double getArea()
{
// b*h/2
return _base * _height / 2;
}
};
class Sphere : public ThreeDimensionalShape
{
protected:
double _radius;
public:
Sphere(double r) : _radius{r}
{}
double getArea()
{
cout << 4 * M_PI * pow(_radius, 2) << endl;
return 4 * M_PI * pow(_radius, 2);
}
double getVolume()
{
return (4/3) * M_PI * pow(_radius, 3);
}
};
class Cube : public ThreeDimensionalShape
{
protected:
double _side;
public:
Cube(double s) : _side{s}
{};
double getArea()
{
// surface area = 6*a^2
return 6 * pow(_side, 2);
}
double getVolume()
{
// a^3
return pow(_side, 3);
}
};
class Tetrahedron : public ThreeDimensionalShape
{
protected:
double _side;
public:
Tetrahedron(double s) : _side{s}
{};
double getArea()
{
// sqrt(3)*a^2
return sqrt(3) * pow(_side, 2);
}
double getVolume()
{
// a^3/6sqrt(2)
return pow(_side, 3) / (6 * sqrt(2));
}
};
int main()
{
Shape arr[2];
arr[0] = Circle{10};
arr[1] = Sphere{10};
// This one is accessing the right method.
cout << "Area of circle: " << arr[0].getArea() << endl;
// This one should access the parent, but accesses the grand parent!
// even if it is overridden in parent.
cout << "Volume of circle: " << arr[0].getVolume() << endl;
// Both of these are accessing methods on grand parent rather than their own!!
cout << "Area of sphere: " << arr[1].getArea() << endl;
cout << "Volume of sphere: " << arr[1].getVolume() << endl;
return 0;
}
我不知道为什么数组方法在最后三行中一直访问祖父函数,但第一行是正确的方法。
这是一个对象切片的案例。你需要把你的对象作为指针,最好是 std::unique_ptr<>
放入你的数组 - 或者再次最好是 std::vector<>
试试这个:
#include <memory>
#include <vector>
// ...
int main()
{
std::vector<std::unique_ptr<Shape>> vec(2);
vec[0] = std::make_unique<Circle>(10);
vec[1] = std::make_unique<Sphere>(10);
// This one is accessing the right method.
cout << "Area of circle: " << vec[0]->getArea() << endl;
// This one should access the parent, but accesses the grand parent!
// even if it is overridden in parent.
cout << "Volume of circle: " << vec[0]->getVolume() << endl;
// Both of these are accessing methods on grand parent rather than their own!!
cout << "Area of sphere: " << vec[1]->getArea() << endl;
cout << "Volume of sphere: " << vec[1]->getVolume() << endl;
return 0;
}
您遇到对象切片。下面的代码部分就是这样做的:
Shape arr[2];
arr[0] = Circle{10};
arr[1] = Sphere{10};
上面的每个赋值调用子类对象的Shape
和slices的复制赋值运算符。您可以使用引用或指针来实现您的意图:
std::unique_ptr<Shape> arr[2];
arr[0] = std::make_unique<Circle>(10);
arr[1] = std::make_unique<Sphere>(10);
大家好,这是我要使用的一些代码 运行,问题是它无法按照我的预期运行。我无法弄清楚它有什么问题。我是c++菜鸟,请帮忙。
#include <iostream>
#include <cmath>
#include <stdexcept>
using namespace std;
/**
* Super class
*/
class Shape
{
protected:
int _dimensions;
public:
Shape() : _dimensions{0}
{};
Shape(int dims) : _dimensions{dims}
{};
virtual double getArea() {};
// Because some shapes have no volume.
virtual double getVolume() {};
void setDimensions(int dim)
{
this->_dimensions = dim;
};
int getDimensions()
{
return this->_dimensions;
};
};
/**
* Extended classes
*/
class TwoDimensionalShape : public Shape
{
public:
TwoDimensionalShape() : Shape{2}
{};
// This should throw an error
double getVolume() {
throw logic_error("This shape ain't got area!");
};
};
class ThreeDimensionalShape : public Shape
{
public:
ThreeDimensionalShape() : Shape{3} {};
};
/**
* Final Concrete classes extending extended classes
*/
class Circle : public TwoDimensionalShape
{
protected:
double _radius;
public:
Circle(double r) : _radius{r}
{};
double getArea()
{
// pi*r^2
return M_PI * pow(_radius, 2);
}
};
class Square : public TwoDimensionalShape
{
protected:
double _side;
public:
Square(double s) : _side{s}
{}
double getArea()
{
// s^2
return pow(_side, 2);
}
};
class Triangle : public TwoDimensionalShape
{
protected:
double _base, _height;
public:
Triangle(double b, double h) : _base{b}, _height{h}
{};
double getArea()
{
// b*h/2
return _base * _height / 2;
}
};
class Sphere : public ThreeDimensionalShape
{
protected:
double _radius;
public:
Sphere(double r) : _radius{r}
{}
double getArea()
{
cout << 4 * M_PI * pow(_radius, 2) << endl;
return 4 * M_PI * pow(_radius, 2);
}
double getVolume()
{
return (4/3) * M_PI * pow(_radius, 3);
}
};
class Cube : public ThreeDimensionalShape
{
protected:
double _side;
public:
Cube(double s) : _side{s}
{};
double getArea()
{
// surface area = 6*a^2
return 6 * pow(_side, 2);
}
double getVolume()
{
// a^3
return pow(_side, 3);
}
};
class Tetrahedron : public ThreeDimensionalShape
{
protected:
double _side;
public:
Tetrahedron(double s) : _side{s}
{};
double getArea()
{
// sqrt(3)*a^2
return sqrt(3) * pow(_side, 2);
}
double getVolume()
{
// a^3/6sqrt(2)
return pow(_side, 3) / (6 * sqrt(2));
}
};
int main()
{
Shape arr[2];
arr[0] = Circle{10};
arr[1] = Sphere{10};
// This one is accessing the right method.
cout << "Area of circle: " << arr[0].getArea() << endl;
// This one should access the parent, but accesses the grand parent!
// even if it is overridden in parent.
cout << "Volume of circle: " << arr[0].getVolume() << endl;
// Both of these are accessing methods on grand parent rather than their own!!
cout << "Area of sphere: " << arr[1].getArea() << endl;
cout << "Volume of sphere: " << arr[1].getVolume() << endl;
return 0;
}
我不知道为什么数组方法在最后三行中一直访问祖父函数,但第一行是正确的方法。
这是一个对象切片的案例。你需要把你的对象作为指针,最好是 std::unique_ptr<>
放入你的数组 - 或者再次最好是 std::vector<>
试试这个:
#include <memory>
#include <vector>
// ...
int main()
{
std::vector<std::unique_ptr<Shape>> vec(2);
vec[0] = std::make_unique<Circle>(10);
vec[1] = std::make_unique<Sphere>(10);
// This one is accessing the right method.
cout << "Area of circle: " << vec[0]->getArea() << endl;
// This one should access the parent, but accesses the grand parent!
// even if it is overridden in parent.
cout << "Volume of circle: " << vec[0]->getVolume() << endl;
// Both of these are accessing methods on grand parent rather than their own!!
cout << "Area of sphere: " << vec[1]->getArea() << endl;
cout << "Volume of sphere: " << vec[1]->getVolume() << endl;
return 0;
}
您遇到对象切片。下面的代码部分就是这样做的:
Shape arr[2];
arr[0] = Circle{10};
arr[1] = Sphere{10};
上面的每个赋值调用子类对象的Shape
和slices的复制赋值运算符。您可以使用引用或指针来实现您的意图:
std::unique_ptr<Shape> arr[2];
arr[0] = std::make_unique<Circle>(10);
arr[1] = std::make_unique<Sphere>(10);