C ++(OOP)中的类和封装

问题描述 投票:2回答:2

我们正在使用OOP在我的课程中进行CPP课程,而且我有点迷失了他们。我理解整个过程 - 我想,但我似乎无法做到正确。我是新手,所以请放轻松我。

基本上,这个分配任务的整个前提是创建以下变量和类:

  1. 创建一个名为Triangle的类
  2. 封装a,b,c - 三角形边长
  3. bool Set(双aa,双bb,双cc); - 设置值并返回true或false,具体取决于是否可以使用基于这些长度的三角形
  4. 双Perim(); - 计算三角形的周长。
  5. 双面积(); - 计算三角形区域。
  6. bool isRect(); - 检查这是否是一个直角三角形。

我希望这是有道理的?

以下是我到目前为止的情况:

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。如果这有道理?

我一直试图绕过这几个小时,我似乎无法把它弄好,希望有人在这里指出我正确的方向?

提前谢谢你,对于凌乱的代码感到抱歉..

c++ class oop encapsulation member
2个回答
4
投票

这是一个可以接受的开始。但这里有几个问题。

Let's go through the header first:

你需要摆脱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(); 

Now to the implementation

首先,您需要避免成员变量和成员函数之间的混淆:

  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函数需要一些返工:你必须返回truefalse。你最好不要在return语句中使用cout,但在返回之前。最后但并非最不重要,您必须在分配成员变量之前执行有效性测试。

Finally to main()

输入和输出流是不同的东西。所以不要试试cin上的<<endl

输入工作后,您可以使用t.set(...)来使用用户输入的值来更改t。

如果t.set(...)返回true,则可以显示函数的结果。例如:

 cout << "Area: " << t.Area()<<endl; 

如果结果为假,则更好地告知用户您不能再使用这样的三角形。

我想你知道编译如何编译main.cpp和triangle.cpp。


3
投票

1) Include header files, not cpp files!

去掉:

    #include "Triangle.cpp"

原因:

cpp文件是编译的。它们依赖于头文件,而不是相反。标头可以依赖于其他标头,这实际上发生了很多。但他们不应该依赖于cpp文件。

2) Wrap headers in ifndef/define blocks.

移动:

#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。没有必要这样做。

3) Fix the triangle class declaration

更改:

    class Triangle(){

    class Triangle {

原因:

你很亲密!但是你混淆了使用声明一个类的语法来声明构造函数的语法。

4) Make functions you intend to use outside of Triangle public.

移动:

double Perim();上方的“public:”访问说明符

原因:

如果你想调用方法:来自main.cpp的Perim,Area和IsRect(或者来自anywehre但三角形类的内部!)你需要将这些方法公开。

你可能想把所有东西都公之于众,但这种形式很糟糕 - 你的导师专门说“封装a,b,c”。您可以谷歌封装设计模式来了解原因。我不会在这里介绍它。

5) Fill out your triangle constructor

看方法:

    Triangle::Triangle(int aa, int bb, int cc)

变化:

  • 在头文件中,您不提供三个参数名称。这不是一个错误,但它很奇怪。您应该给出这些参数名称。
  • 在你的另一个构造函数(没有参数的构造函数)中,你表明你知道如何分配a,b和c一个值!继续并在此方法中为它们分配值。
  • 考虑一下你是否真的想使用int作为参数的类型。您将边长存储为双精度,但是您将它们作为整数提供给构造函数。这不是一个错误,但它很奇怪。

6) Fix the body of the Set method.

看方法:

    Triangle::Set(double aa, double bb, double cc)

注意:

记住一种方法是交换。你提供它的参数,它做了一些工作,它返回给你一些价值(除非它'返回'无效)。你的方法是要求3个双打,并返回一个布尔。如果你要归还一个布尔,你就同意给出一个真值或假值。在这里,你要回报任何cout <<“......”;回报。这听起来不像你想要的(即使它编译)。你不关心cout什么回来,对吧?

变化:

不要在这个功能上做任何事情。如果三角形可能则返回true,如果不可能则返回false。你可以从调用Set的地方cout你想要的任何东西。

7) Encapsulate a, b, c.

你做了一个私人的b和c。这是封装的一半。您的教师可能希望您在Triangle中为这些变量编写一个getter和setter。

例:

    double Triangle::GetA() {
        return a;
    }

    void Triangle::SetA(double aa) {
        a = aa;
    }

我会把它作为锻炼来做其余的事情。

8) Using your Triangle in main.cpp

如果你使用局部变量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的调用以获取用户输入后,请执行以下操作:

  • 创建一个布尔变量来存储set的结果,稍后我们将使用它。
  • 在t上调用Set函数,提供用户输入的3个长度。在我们的布尔值中存储Set的返回值。
  • 写一个if语句。检查该布尔值是否为true。如果是,则打印“可以使用具有这些参数的三角形。”,否则打印“不能使用具有这些参数的三角形”。
  • 如果你的作业要求你做任何其他或不同的事情,比如打印Perim,Area和isRect的结果,那就去做吧!
© www.soinside.com 2019 - 2024. All rights reserved.