[英]Classes and encapsulation in C++ (OOP)
我們正在使用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中使用,而不是在頭文件中使用,因為它會導致包含頭文件的文件忽略導入另一個命名空間,這可能會在以后創建沖突(在較大的項目中) 。 有關如何在此處使用標頭的更多建議。
然后Triangle
是一個類而不是一個函數。 所以你必須用class 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
,但在返回之前。 最后但並非最不重要,您必須在分配成員變量之前執行有效性測試。
輸入和輸出流是不同的東西。 所以不要嘗試<<endl
on cin!
輸入工作后,您可以使用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:”訪問說明符double Perim();
原因:
如果你想調用方法:來自main.cpp的Perim,Area和IsRect(或者來自anywehre但三角形類的內部!)你需要將這些方法公開。
你可能想把所有東西都公之於眾,但這種形式很糟糕 - 你的導師專門說“封裝a,b,c”。 您可以谷歌封裝設計模式來了解原因。 我不會在這里介紹它。
看方法:
Triangle::Triangle(int aa, int bb, int cc)
變化:
在頭文件中,您不提供三個參數名稱。 這不是一個錯誤,但它很奇怪。 您應該給出這些參數名稱。
在你的另一個構造函數(沒有參數的構造函數)中,你表明你知道如何分配a,b和ca值! 繼續並在此方法中為它們分配值。
考慮一下你是否真的想使用int
作為參數的類型。 您將邊長存儲為雙精度,但是您將它們作為整數提供給構造函數。 這不是一個錯誤,但它很奇怪。
看方法:
Triangle::Set(double aa, double bb, double cc)
注意:
記住一種方法是交換。 你提供它的參數,它做了一些工作,它返回給你一些價值(除非它'返回'無效)。 你的方法是要求3個雙打,並返回一個布爾。 如果你要歸還一個布爾,你就同意給出一個真值或假值。 在這里,你要回報任何cout <<“......”; 回報。 這聽起來不像你想要的(即使它編譯)。 你不關心cout什么回來,對吧?
變化:
不要在這個功能上做任何事情。 如果三角形可能則返回true,如果不可能則返回false。 你可以從調用Set的地方cout你想要的任何東西。
你把ab和c私有化了。 這是封裝的一半。 您的教師可能希望您在Triangle中為這些變量編寫一個getter和setter。
例:
double Triangle::GetA() {
return a;
}
void Triangle::SetA(double aa) {
a = aa;
}
我會把它留作exersize來做其余的事情。
如果你使用局部變量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的調用以獲取用戶輸入后,請執行以下操作:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.