我修改了這個類,並決定保留原始答案以供參考。現在這個版本在設計上更加優雅;然而,如果我使用我的錯誤處理程序/記錄器庫,它可能會更清潔,但將它們包含在這個答案中是爲了適合這裏的一個規模,但主函數將設置在try catch塊中,並且我的錯誤處理程序和記錄器可以在錯誤非常嚴重的情況下拋出錯誤並退出程序,或者如果值無效但將程序的操作仍然處於可接受的狀態以繼續,則可以將消息記錄到控制檯窗口或文件。
該類有點臃腫,錯誤消息通常不需要存在,但用作演示以顯示正確的程序邏輯流程。
這裏是我對user1024
所說的更新的類和主函數,它解決了根據字段值設置布爾標誌變量的問題,而不是調用哪個函數。現在,他可以擁有未初始化爲類的默認值,然後使用相同的默認值初始化類。該類的狀態現在基於函數調用而不是成員值。
Temp.h
#ifndef TEMP_H
#define TEMP_H
class Temp {
friend std::ostream& operator<<(std::ostream& os, const Temp& t);
private:
int m_a, m_b, m_c;
double m_d, m_e, m_f;
bool m_isInitialized;
bool m_updated;
const std::string m_strInitMessage = std::string("First stage values must be initalized before calling this funciton.\n");
const std::string m_strUpdateMessage = std::string("setUpdateStage needs to be called first before modifying this value.\n");
public:
Temp();
Temp(int a, int b, int c);
Temp(int a, int b, int c, double d, double e, double f);
void setInitialStage(int a, int b, int c);
void setUpdateStage(double d, double e, double f);
bool isInitialized() const;
bool isUpdated() const;
int getA() const;
int getB() const;
int getC() const;
// These Are Updating Functions Not Setting Functions setInitialStage Must Be Called First
void updateA(int a);
void updateB(int b);
void updateC(int c);
double getD() const;
double getE() const;
double getF() const;
// These Are Updating Functions Not Setting Functions Both setInitialStage & setUpdateStage Must Be Called First
void updateD(double d);
void updateE(double e);
void updateF(double f);
private:
// Helper Function
bool testStages();
}; // Temp
#endif // TEMP_H
Temp.cpp
#include "stdafx.h"
#include "Temp.h"
std::ostream& operator<<(std::ostream& os, const Temp& t) {
if (t.isUpdated()) {
os << t.getA() << " " << t.getB() << " " << t.getC() << " "
<< t.getD() << " " << t.getE() << " " << t.getF() << std::endl;
return os;
} else {
os << t.getA() << " " << t.getB() << " " << t.getC() << std::endl;
return os;
}
} // operator<<
Temp::Temp() :
m_a(0),
m_b(0),
m_c(0),
m_d(0),
m_e(0),
m_f(0),
m_isInitialized(false),
m_updated(false) {
} // Temp
Temp::Temp(int a, int b, int c) :
m_a(a),
m_b(b),
m_c(c),
m_d(0.0),
m_e(0.0),
m_f(0.0),
m_isInitialized(true),
m_updated(false) {
} // Temp
Temp::Temp(int a, int b, int c, double d, double e, double f) :
m_a(a),
m_b(b),
m_c(c),
m_d(d),
m_e(e),
m_f(f),
m_isInitialized(true),
m_updated(true) {
} // Temp
void Temp::setInitialStage(int a, int b, int c) {
// Do Nothing With 2nd Stage Variables And Update Flag
if (!m_isInitialized) {
m_a = a;
m_b = b;
m_c = c;
m_isInitialized = true;
} else {
// Do not Reinitalize
std::cout << "Initial stage values are already initialized, please use the individual update functions.\n";
return;
}
} // setInitialStage
void Temp::setUpdateStage(double d, double e, double f) {
// Check To See If This Has Been Intialized First
if (!m_isInitialized) {
std::cout << "\nFirst Stage values must be initialized first\n";
return;
} else {
if (!m_updated) {
// Do nothing with Initial Values
m_d = d;
m_e = e;
m_f = f;
m_updated = true;
} else {
// Do Not Reinitalize
std::cout << "Update stage values have already been initialized, please use the individual update functions.\n";
return;
}
}
} // setUpdateStage
bool Temp::isInitialized() const {
return m_isInitialized;
} // isInitialized
bool Temp::isUpdated() const {
return m_updated;
} // isUpdated
int Temp::getA() const {
if (!m_isInitialized) {
std::cout << "m_a has not been initialized\n";
return 0;
}
return m_a;
} // getA
int Temp::getB() const {
if (!m_isInitialized) {
std::cout << "m_b has not been initialized\n";
return 0;
}
return m_b;
} // getB
int Temp::getC() const {
if (!m_isInitialized) {
std::cout << "m_c has not been initialized\n";
return 0;
}
return m_c;
} // getC
void Temp::updateA(int a) {
if (!m_isInitialized) {
std::cout << m_strInitMessage;
return;
}
m_a = a;
} // updateA
void Temp::updateB(int b) {
if (!m_isInitialized) {
std::cout << m_strInitMessage;
return;
}
m_b = b;
} // updateB
void Temp::updateC(int c) {
if (!m_isInitialized) {
std::cout << m_strInitMessage;
return;
}
m_c = c;
} // updateC
double Temp::getD() const {
if (!m_updated) {
std::cout << "m_d has not been initialized\n";
return 0;
}
return m_d;
} // getD
double Temp::getE() const {
if (!m_updated) {
std::cout << "m_e has not been initialized\n";
return 0;
}
return m_e;
} // getE
double Temp::getF() const {
if (!m_updated) {
std::cout << "m_f has not been initialized\n";
return 0;
}
return m_f;
} // getF
bool Temp::testStages() {
if (!m_isInitialized) {
std::cout << m_strInitMessage;
return false;
} else {
if (!m_updated) {
std::cout << m_strUpdateMessage;
return false;
}
}
return true;
} // testStages
void Temp::updateD(double d) {
if (!testStages()) {
return;
}
m_d = d;
} // updateD
void Temp::updateE(double e) {
if (!testStages()) {
return;
}
m_e = e;
} // updateE
void Temp::updateF(double f) {
if (!testStages()) {
return;
}
m_f = f;
} // update
的main.cpp
#include "stdafx.h"
#include "Temp.h"
int main() {
Temp t1;
std::cout << "Default constructor called." << std::endl;
std::cout << t1 << std::endl;
// Error Cases
std::cout << "Error Cases For Default Constructor Before setInitialStage is called:" << std::endl;
std::cout << "---------------------------------------------------------------------" << std::endl;
std::cout << "Trying to update a first stage value before setInitialStage is called." << std::endl;
t1.updateA(1);
std::cout << t1 << std::endl;
std::cout << "Trying to update a second stage value before setInitialStage is called." << std::endl;
t1.updateD(2.3);
std::cout << t1 << std::endl;
std::cout << "Trying to call setUpdateStage before m_isInitialized = true" << std::endl;
t1.setUpdateStage(4.5, 6.7, 8.9);
std::cout << t1 << std::endl;
// 1st Stage Initialization WRT To Using A Default Constructor
std::cout << "After setInitalStage is called" << std::endl;
t1.setInitialStage(1, 2, 3);
std::cout << t1 << std::endl;
// Error Cases
std::cout << "Error Cases For Default Constructor After setInitialStage is called:" << std::endl;
std::cout << "--------------------------------------------------------------------" << std::endl;
std::cout << "Calling setInitialStage after it has already been called." << std::endl;
t1.setInitialStage(4, 5, 6);
std::cout << t1 << std::endl;
std::cout << "Trying to update a second stage value after setInitialStage and before setUpdateStage have been called." << std::endl;
t1.updateD(7.8);
std::cout << t1 << std::endl;
std::cout << "Updating a first stage value after setInitialStage is called." << std::endl;
t1.updateB(9);
std::cout << t1 << std::endl;
std::cout << "Calling setUpdatedStage." << std::endl;
t1.setUpdateStage(10.11, 12.13, 14.15);
std::cout << t1 << std::endl;
// Error Case
std::cout << "Error Case For Default Constructor After Both\n setInitialStage & setUpdateStage have been called." << std::endl;
std::cout << "------------------------------------------------" << std::endl;
std::cout << "Calling setUpdateStage after it has already been called." << std::endl;
t1.setUpdateStage(16.17, 18.19, 20.21);
std::cout << t1 << std::endl;
std::cout << "Updating second stage value afer both setInitializeStage & setUpdateStage have been called." << std::endl;
t1.updateF(22.23);
std::cout << t1 << std::endl << std::endl;
Temp t2(1, 2, 3);
std::cout << "First stage constructor called" << std::endl;
std::cout << t2 << std::endl;
// Error Cases
std::cout << "Error Cases For 1st Stage Constructor" << std::endl;
std::cout << "-------------------------------------" << std::endl;
std::cout << "Calling setInitialStage after using this constructor." << std::endl;
t2.setInitialStage(4, 5, 6);
std::cout << t2 << std::endl;
std::cout << "Trying To Update Second Stage Value Before setUpdateStage is called." << std::endl;
t2.updateD(7.8);
std::cout << t2 << std::endl;
std::cout << "Updating 1st Stage Value" << std::endl;
t2.updateB(9);
std::cout << t2 << std::endl;
std::cout << "Calling setUpdateStage" << std::endl;
t2.setUpdateStage(10.11, 12.13, 14.15);
std::cout << t2 << std::endl;
// Error Case
std::cout << "Error Case For 1st Stage Constructor After setUpdateStage has been called." << std::endl;
std::cout << "-------------------------------------------------------------------------" << std::endl;
t2.setUpdateStage(16.17, 18.19, 20.21);
std::cout << t2 << std::endl;
std::cout << "Updating 2nd stage value." << std::endl;
t2.updateE(22.23);
std::cout << t2 << std::endl << std::endl;
Temp t3(1, 2, 3, 4.5, 6.7, 8.9);
std::cout << "Full Stage Constructor Called" << std::endl;
std::cout << t3 << std::endl;
// Error Cases
std::cout << "Error Cases For Full Stage Constructor:" << std::endl;
std::cout << "---------------------------------------" << std::endl;
std::cout << "Calling setInitialStage" << std::endl;
t3.setInitialStage(10, 11, 12);
std::cout << t3 << std::endl;
std::cout << "Calling setUpdateStage" << std::endl;
t3.setUpdateStage(13.14, 15.16, 17.18);
std::cout << t3 << std::endl;
std::cout << "Updating 1st & 2nd Stage Values" << std::endl;
t3.updateA(19);
t3.updateD(20.21);
std::cout << t3 << std::endl;
std::cout << "With this design 0 is now an acceptable value." << std::endl;
std::cout << "Updating all of t3's values." << std::endl;
t3.updateA(0);
t3.updateB(0);
t3.updateC(0);
t3.updateD(0);
t3.updateE(0);
t3.updateF(0);
std::cout << t3 << std::endl;
std::cout << "Using Default Constructor To Show That Both stageFunctions Can accept 0 as value" << std::endl;
Temp t4;
std::cout << "Unitialized:" << std::endl
<< t4 << std::endl;
std::cout << "Calling setInitialStage" << std::endl;
t4.setInitialStage(0, 0, 0);
std::cout << t4 << std::endl;
std::cout << "Calling setUpdateStage" << std::endl;
t4.setUpdateStage(0, 0, 0);
std::cout << t4 << std::endl;
std::cout << std::endl; // Used As A Break Point Before Application End
return 0;
} // main
利用具有3構建此類您可以通過以下三種方式創建此類:創建一個空的未初始化版本,以便稍後填寫所有部分,第一階段在施工時設置,以便稍後更新第二階段,最後完成施工過程中的所有階段。這也表明,所有3個構造函數,所有初始化函數,更新函數和getter都通過相同std::ostream << operator
工作。它還演示瞭如何按特定順序調用特定函數,並演示何時不調用特定函數重複次數。我相信還有很多其他方法可以實現,但能夠看到以幾種成功方式完成相同任務的優點。
你究竟在做什麼?第二個重載會解決什麼問題?你能告訴我們你想如何使用輸出操作符嗎?另外,請閱讀關於[XY問題](http://xyproblem.info/),這與您的問題非常相關。 –
那麼,你的鏈接是有幫助的。在我的問題中,我想在兩個階段寫'MyClass'。在第一階段,我需要存儲一些額外的信息,比如'b','f','h',然後,我合併所有臨時文件並存儲'a','c','d','e', 'g'。所以,如果有兩個'<<'的情況,它會很方便。謝謝。 – user1024
「MyClass」的「type1」和「type2」實例,它們有多獨特?是否可以通過創建兩個類來解決:'MyClass2'具有'a','c','d'和'g'成員,然後是從MyClass2繼承的MyClass1並添加對其他類的支持成員? –