我们正在使用OOP在我的课程中进行CPP课程,而且我有点迷失了他们。我理解整个过程 - 我想,但我似乎无法做到正确。我是新手,所以请放轻松我。
基本上,这个分配任务的整个前提是创建以下变量和类:
我希望这是有道理的?
以下是我到目前为止的情况:
main.cpp文件(远非完整,此刻就像占位符一样):
#include <iostream>
#include "triangle.h"
using namespace std;
int main() {
Triangle t;
int aa, bb, cc;
cout <<"Triangle side 1 - " <<endl;
cin >> aa <<endl;
cout <<"Triangle side 2 - ";
cin >> bb <<endl;
cout <<"Triangle side 3 - ";
cin >> cc <<endl;
return 0;
}
Triangle.h文件:
#include <iostream>
#include "Triangle.cpp"
using namespace std;
#ifndef TRIANGLE_H
#define TRIANGLE_H
class Triangle(){
private:
double a;
double b;
double c;
double Perim();
double Area();
bool IsRect();
public:
Triangle();
Triangle(int, int, int);
bool set(double aa, double bb, double cc);
};
#endif
和Triangle.cpp文件(用公式计算一切)
#include "Triangle.h"
Triangle::Triangle(){
a = b = c = 0;
Perim = 0.0;
Area = 0.0;
}
Triangle::Triangle(int aa, int bb, int cc){
}
double Triangle::Perim(){
return a + b + c;
}
double Triangle::Area(){
s = (a+b+c)/2;
Area = SQRT(s(s-a)(s-b)(s-c));
return Area;
}
bool Triangle::isRect(){
return (((a*a) + (b*b)) == (c*c)) ? true : false; //---checks if this is a right angle triangle, and should return true or false.
}
bool Triangle::Set(double aa, double bb, double cc){
a = aa;
b = bb;
c = cc;
if (a + b > c && a + c > b && b + c > a){//if one of these criteria is false, then a triangle is not possible.
return cout << "A triangle with these parameters is possible.";
}
else{
return cout << "A triangle with these parameters is NOT possible.";
}
}
当然,这远非完整,但我努力将所有事物联系在一起。我试图获取Main.cpp文件,当人输入值时,应该传递给其他cpp文件并进行计算,并且一旦完成,就通过对象(尚未创建)将值返回到Main cpp。如果这有道理?
我一直试图绕过这几个小时,我似乎无法把它弄好,希望有人在这里指出我正确的方向?
提前谢谢你,对于凌乱的代码感到抱歉..
这是一个可以接受的开始。但这里有几个问题。
你需要摆脱cpp文件的#include
。您应该只在标头中包含标头。最好将自己限制在标题中代码所需的标题中。例如,类定义并不真正需要<iostream>
。因此将此包含移动到需要它的cpp。
您还需要摆脱using
子句:这应该在cpp中使用,而不是在头文件中使用,因为它会导致包含头文件的文件忽略导入另一个命名空间,这可能会在以后创建冲突(在较大的项目中) 。关于如何使用标头here的更多建议。
然后Triangle
是一个类而不是一个函数。所以你必须用class Triangle { ... };
而不是class Triangle() {...};
来定义它
我还希望以下成员函数是公开的:
double Perim(); // These are definitively of interest for users of Triangles
double Area();
bool IsRect();
首先,您需要避免成员变量和成员函数之间的混淆:
Triangle::Triangle(){
a = b = c = 0;
// Perim = 0.0; // NO !! Perim() is a function, you cannot assign a value to it
// Area = 0.0;
}
然后你需要声明你使用的变量:
double Triangle::Area(){
auto s = (a+b+c)/2; // because s deosn't exist
return std::sqrt(s*(s-a)*(s-b)*(s-c)); // sqrt requires include <cmaths>
// multiplication must be explicit.
}
然后你可以返回一个布尔表达式。无需更明确:
bool Triangle::isRect(){
return ((a*a) + (b*b)) == (c*c);
}
最后,你的set函数需要一些返工:你必须返回true
或false
。你最好不要在return语句中使用cout
,但在返回之前。最后但并非最不重要,您必须在分配成员变量之前执行有效性测试。
输入和输出流是不同的东西。所以不要试试cin上的<<endl
!
输入工作后,您可以使用t.set(...)
来使用用户输入的值来更改t。
如果t.set(...)
返回true,则可以显示函数的结果。例如:
cout << "Area: " << t.Area()<<endl;
如果结果为假,则更好地告知用户您不能再使用这样的三角形。
我想你知道编译如何编译main.cpp和triangle.cpp。
去掉:
#include "Triangle.cpp"
原因:
cpp文件是编译的。它们依赖于头文件,而不是相反。标头可以依赖于其他标头,这实际上发生了很多。但他们不应该依赖于cpp文件。
移动:
#ifndef TRIANGLE_H
和#define TRIANGLE_H
在文件顶部高于一切。在风格上你可能想要评论文件在ifndef / define块上面而不是在下面的内容
例:
// This is the triangle header file! Here is where I describe it.
#ifndef TRIANGLE_H
#define TRIANGLE_H
// TODO: Put the includes here
// TODO: Put your class here
#endif
原因:
在C ++中,你可以想到这一行:#include <iostream>
将iostream文件的内容复制粘贴到该行的上方。因此,当您在main.cpp和triangle.cpp中#include“triangle.h”时,您将描述三角形类对每个cpp文件的外观。 main.cpp需要知道它可以创建和使用三角形,而triangle.cpp需要知道它才能正确实现Triangle中的函数。
如果您包含两次文件,则该文件将被有效地复制粘贴两次。通常,这将重新定义其内容,这将是编译错误。 ifndef / define块的作用是“嘿,如果尚未定义TRIANGLE_H,这是它第一次被包含。所以继续定义TRIANGLE_H,以及所有文件内容。下一次triangle.h是包括我们将看到TRIANGLE_H已经定义,我们跳过该标题的内容,而不是重新定义Trinagle是什么。
我建议你把它移到顶部的原因是你包括iostream,triangle.cpp(我们已经讨论过那个部分)并且每次包含triangle.h时都使用命名空间std。没有必要这样做。
更改:
class Triangle(){
至
class Triangle {
原因:
你很亲密!但是你混淆了使用声明一个类的语法来声明构造函数的语法。
移动:
double Perim();
上方的“public:”访问说明符
原因:
如果你想调用方法:来自main.cpp的Perim,Area和IsRect(或者来自anywehre但三角形类的内部!)你需要将这些方法公开。
你可能想把所有东西都公之于众,但这种形式很糟糕 - 你的导师专门说“封装a,b,c”。您可以谷歌封装设计模式来了解原因。我不会在这里介绍它。
看方法:
Triangle::Triangle(int aa, int bb, int cc)
变化:
int
作为参数的类型。您将边长存储为双精度,但是您将它们作为整数提供给构造函数。这不是一个错误,但它很奇怪。看方法:
Triangle::Set(double aa, double bb, double cc)
注意:
记住一种方法是交换。你提供它的参数,它做了一些工作,它返回给你一些价值(除非它'返回'无效)。你的方法是要求3个双打,并返回一个布尔。如果你要归还一个布尔,你就同意给出一个真值或假值。在这里,你要回报任何cout <<“......”;回报。这听起来不像你想要的(即使它编译)。你不关心cout什么回来,对吧?
变化:
不要在这个功能上做任何事情。如果三角形可能则返回true,如果不可能则返回false。你可以从调用Set的地方cout你想要的任何东西。
你做了一个私人的b和c。这是封装的一半。您的教师可能希望您在Triangle中为这些变量编写一个getter和setter。
例:
double Triangle::GetA() {
return a;
}
void Triangle::SetA(double aa) {
a = aa;
}
我会把它作为锻炼来做其余的事情。
如果你使用局部变量t
,你可以像这样调用函数:
t.SetA(1.1);
cout << t.GetA() << endl; // will print 1.1
double theValueOfA; // local variable
theValueOfA = t.GetA(); // store the result of GetA in our new variable
cout << theValueOfA << endl; // will also print 1.1
有了这些信息,在您完成对cin的调用以获取用户输入后,请执行以下操作: