我似乎无法让我的气缸类正确执行其打印和音量功能 . 以下是赋值的说明:设计一个名为Shape的类,它是一个抽象基类 . Shape有两个纯虚函数,printShapeName和print .
Shape包含另外两个虚函数,area和volume,每个函数都有一个返回零值的默认实现 .
Point类从Shape继承这些实现(点的面积和体积均为零) . Point具有x和y坐标私有成员 .
Class Circle派生自具有公共继承的Point . 圆的体积为0.0,因此不会覆盖基类成员函数体积 . 圆形具有非零区域,因此在此类中覆盖区域功能 . 写入get和set函数以返回并为Circle指定新的半径 .
Class Cylinder派生自Circle并具有公共继承 . A Cylinder的面积和体积与Circle的面积和体积不同,因此该类别中的面积和体积函数都被覆盖 . 写入get和set函数以返回高度并指定新的高度 .
创建一个点,一个圆和一个圆柱然后打印结果 .
//
// Shape.hpp
// HW6_VirtualFunctions
//
// Created by Aviv Fedida on 11/25/17.
// Copyright © 2017 Aviv Fedida. All rights reserved.
//
#ifndef Shape_hpp
#define Shape_hpp
#include <stdio.h>
#include <iostream>
#include <cmath>
using namespace std;
class Shape {
protected: // protected members
double width, height, radius, pi, x, y;
public:
void setWidth(double a); // prototype for width setter
void setHeight(double b); // prototype for height setter
void setX(double c);
void setY(double d);
void setRad(double r);
void setPi(double p);
double getWidth() { // get width to return only
return width;
}
double getHeight() { // get height to return only
return height;
}
double getX() {
return x;
}
double getY() {
return y;
}
double getRad() {
return radius;
}
double getPi() {
return pi;
}
// Create public virtual functions
virtual void printShapeName() = 0; // pure virtual for printing shape's name
virtual void print(double a, double b) = 0; // pure virtual print function
virtual double area() { // virtual area function returns default null
return 0;
}
virtual double volume() { // virtual default volume function returns null
return 0;
}
}; // END BASE CLASS -------------------------------------------------------------------------------------
class Point: public Shape {
// x & y coordinates needed for a point
public:
// Prototypes for print & set functions
void printShapeName();
void print(double a, double b);
}; // end first derived class ------------------------------------------------------------------------
class Circle: public Point {
public:
// Protoypes for print functions
void printShapeName();
void print(double r, double p);
// Prototypes for area & volume functions
double area(double r, double p);
}; // end second derived class ----------------------------------------------------------------------------
class Cylinder: public Circle {
public:
double area(double r, double p);
void printShapeName();
double volume(double r, double p, double h);
void print(double r, double p, double h);
}; // end third and final derived class --------------------------------------------------------------------------
// Some definitions outside classes
//-------------------------------------------------- BEGIN -----------------------------------------------------------
// Shape base class setter functions defined
void Shape::setWidth(double a) {
width = a;
}
void Shape::setHeight(double b) {
height = b;
}
void Shape::setX(double c) {
x = c;
}
void Shape::setY(double d) {
y = d;
}
void Shape::setRad(double r) {
radius = r;
}
void Shape::setPi(double p) {
p = 3.1416;
pi = p;
}
void Point::printShapeName() { // Print name of class
cout << "Point " << endl;
}
void Point::print(double a, double b) { // Print values within class
cout << "(" << a << "," << b << ")" << endl;
}
void Circle::printShapeName() {
cout << "Circle " << endl;
}
// Circle area function defined
double Circle::area(double r, double p) {
double area;
area = p*(pow(r,2));
return area;
}
void Circle::print(double r, double p) {
cout << "Area of circle is: " << area(r, p) << endl;
cout << "Volume of circle is: " << volume() << endl;
}
void Cylinder::printShapeName() {
cout << "Cylinder " << endl;
}
double Cylinder::area(double r, double p) {
double area;
area = 2*p*r;
return area;
}
double Cylinder::volume(double r, double p, double h) {
double volume;
volume = p*(pow(r,2))*h;
return volume;
}
void Cylinder::print(double r, double p, double h) {
cout << "Area of cylinder is: " << area(r, p) << endl;
cout << "Volume of cylinder is: " << volume(r, p, h) << endl;
}
#endif /* Shape_hpp */
//
// main.cpp
#include <iostream>
#include "Shape.hpp"
#include "Shape.cpp"
using namespace std;
int main() {
double pi = 3.1416; // Variable for pi
// Instantiate class objects
Point guard;
Circle k;
Cylinder cid;
// Instantiate pointers to class objects
Shape *pptr;
Shape *kptr;
Shape *cptr;
// Assign memory of objects to pointer variables
pptr = &guard;
kptr = &k;
cptr = &cid;
// Call objects via pointers and print members
pptr->printShapeName();
pptr->print(5,6);
cout << '\n';
kptr->printShapeName();
kptr->print(9,pi);
cout << '\n';
cptr->printShapeName();
cptr->getHeight();
cptr->setHeight(8);
cptr->print(5,pi);
return 0;
}
如果我尝试在Cylinder类的print函数中添加第三个height参数,则会出错 . 它最终使用我的Circle类定义 .
1 回答
如果你还没有找到答案,
cptr->print(5,pi);
用2个参数调用print
.Circle
有一个2参数print
Cylinder
有一个3参数print
. 由于Cylinder
从Circle
继承了2参数print
,因此Cylinder
打印为Circle
.JakeFreeman的评论可能没有帮助,但它完全正确 . 让我们尝试使其有用,而无需重复教科书的几个章节 .
你已经碰到了两个主要的OO概念:封装和多面体 .
封装是这里的主要问题,处理它解决了多态性问题 .
Cylinder
对象应代表一个且仅代表一个Cylinder . 应该将半径和高度存储在其中 . 调用函数并传入半径和高度在意识形态上是错误的 . 在Cylinder
上执行方法时,它应该已经知道它的半径和高度 .volume
方法不应该使用任何参数,因为计算卷所需的所有内容都应该已知 . 这允许任何形状具有相同的volume
界面,即使支持界面的方法对于每个形状可能是不同的 .完全相同的逻辑适用于区域 .
接下来,并非所有形状都具有半径,因此
Shape
应该对半径一无所知 . 或高度 . 或深度 . 也许形状知道一些锚定点,但这是关于所有形状应该知道的 .同样地,
print
应该不需要参数,除了可能是要打印到的IO流的引用,因为IOstream并不是人们通常期望Cylinder知道或关心的内容 .一个唠叨:为什么要传递pi?如果你有一个pi不是常数的系统,你就有一个奇怪的系统 .
修改形状:
注意没有设置任何形状的骨头 . 在一个正方形上强制
setRadius
函数只是简单的愚蠢 .另请注意,这消除了
Point
的需要,但这是一件好事 . 圆是一种点吗?没有 . 圆圈是一个点 . 除极少数例外情况外,除非存在所谓的is-a关系,否则不要延长 . 正方形是一个专门的矩形 . 矩形是一种特殊的形状 . 但这两点都不重要 .我建议将
setX
和setY
分组到同时执行这两个操作的setPosition
中,因为稍后您可以更轻松地将其转换为原子事务 .修订
Circle
:Circle
添加了需要添加到Shape
的内容 . 而已 . 没什么 .Cylinder
也会这样做 . 它是一个圆圈加height
,height
的访问器,使用Circle
的area
方法和height
的卷计算,它自己的area
方法来计算其表面区域,另一个打印方法打印出它的统计数据附录:如果你的编译器支持它,那么它应该利用
override
关键字 . 如果编译器找到一个标记为override的方法并且它没有覆盖任何东西,那么你会得到一个很好的干净错误消息,而不是一堆调试 .