有没有办法将派生类作为 if-else 语句中的条件传递?

is there a way to pass derived classes as a condition in an if-else statement?

本文关键字:语句 条件 if-else 派生 有没有      更新时间:2023-10-16

我有一个虚拟函数,我想创建一个使用派生类作为条件的函数。因此,在下面的代码中,class Video_Games的变量shipcost为 4.99。等等电话,香肠和相册。如果有的话,我如何才能将类作为 if-else 语句中的条件传递,该语句位于名为"Package"的大类内的虚函数中?我想这样做,以便我可以在打印的收据中调用shipcost,该收据确切地知道如何显示每个类别的正确运输。

#include <iostream>
#include <string>
#include <iomanip>
#include <chrono>
#include <ctime>
using namespace std;
class Package
{
protected:
string name_and_address = "?";
double cost = 0.0;
double discount = 0.0;
double discount_rate = 0.0;
bool overnight_delivery = false;
bool insured = false;
string package_contents = "?";
double shipcost = 0.0;
public:
Package() {};
~Package() {};
protected:
virtual double calculate_cost() = 0;
virtual double shipping_cost()
{
if (class Video_Games :public Package) //getting error here that says class or struct definition is missing 
shipcost = 4.99;
else if (class Genius_Phone :public Package) //getting error here that says class or struct definition is missing 
shipcost = 25.00;
else if (class Sausage :public Package) //getting error here that says class or struct definition is missing 
shipcost = 9.00;
else
shipcost = 50.00;
return shipcost;
}
virtual double calculate_discount()
{
if (cost > 1000)
discount_rate = 0.033;
else if (cost > 500)
discount_rate = 0.028;
else if (cost > 200)
discount_rate = 0.024;
else
discount_rate = 0.019;
return cost * discount_rate;
}
friend ostream& operator<<(ostream &out, const Package &Package_Instance)
{
return Package_Instance.print(out);
}

ostream& print(ostream& out) const
{
chrono::system_clock::time_point now = chrono::system_clock::now();
time_t now_c = chrono::system_clock::to_time_t(now + chrono::hours(24));
chrono::system_clock::time_point now2 = chrono::system_clock::now();
time_t now2_c = chrono::system_clock::to_time_t(now2 + chrono::hours(72));
cout << "       *** BILL FOR GOODS ***n";
cout << "Customer: " << endl << endl;
cout << setprecision(2) << showpoint << fixed;
cout << name_and_address << endl;
cout << (overnight_delivery ? (put_time(localtime(&now_c), "Expected Arrival Date: %F")) : put_time(localtime(&now2_c), "Expected Arrival Date: %F")) << endl << endl;
cout << package_contents << endl;
cout << (insured ? "{INSURED}n" : "{NOT INSURED}n");
cout << (overnight_delivery ? "Expedited Shippingn" : "Standard Shippingn");
cout << shipcost << endl; //This is where I want the shipcost to display the dollar amount that corresponds directly to the type of shipcost used for each derived class. So video games would be 4.99, albums would be 50.00 etc. etc. etc. 
cout << "Total Cost is: $" << cost << endl;
cout << "Discount Percentage is: " << discount_rate * 100 << "%" << " for a discount of $" << discount << endl;
cout << "Total Cost after discount is $" << cost - discount << endl << endl;
return out;
}
};
class Video_Games :public Package
{
private:
int num_games = 0;
public:
Video_Games(string location, int number_of_games, bool express, bool insurance)
{
num_games = number_of_games;
name_and_address = location;
overnight_delivery = express;
insured = insurance;
package_contents = to_string(num_games) + " Video Game(s)";
cost = calculate_cost();
discount = calculate_discount();
shipcost = shipping_cost();
}
~Video_Games() {};
protected:
double calculate_cost()
{
cost = num_games * 19.99;
if (overnight_delivery) { cost += shipcost; } //this would be 4.99, and so and so forth for the rest of the classes (not edited yet, but I will edito those when I can nail this baby down). 
if (insured) { cost *= 1.06; }
return cost;
}
};
class Genius_Phone :public Package
{
private:
int num_phones = 0;
int num_cases = 0;
public:
Genius_Phone(string location, int number_of_phones, bool express, bool insurance, int number_of_cases)
{
num_phones = number_of_phones;
name_and_address = location;
overnight_delivery = express;
insured = insurance;
num_cases = number_of_cases;
package_contents = to_string(num_phones) + " Genius Phone(s), " +
(num_cases > 0 ? "and " + to_string(num_cases) + " cases " : "");
cost = calculate_cost();
discount = calculate_discount();
}
~Genius_Phone() {};
protected:
double calculate_cost()
{
cost = num_phones * 699.99 + num_cases * 24.99;
if (overnight_delivery) { cost += 25.00; }
if (insured) { cost *= 1.11; }
return cost;
}
};
class Sausage :public Package
{
private:
int num_Hot_Dogs = 0;
int num_Condiments = 0;
int num_Hot_Dog_Buns = 0;
public:
Sausage(string location, int hotdogs, bool express, bool insurance, int condiments, int buns)
{
num_Hot_Dogs = hotdogs;
name_and_address = location;
overnight_delivery = express;
insured = insurance;
num_Condiments = condiments;
num_Hot_Dog_Buns = buns;
package_contents = to_string(num_Hot_Dogs) + " Hot Dog(s), " +
(num_Condiments > 0 ? to_string(num_Condiments) + " Condiment(s) " : "") +
(num_Hot_Dog_Buns > 0 ? "and " + to_string(num_Hot_Dog_Buns) + " Hot Dog Bun(s) " : "");
cost = calculate_cost();
discount = calculate_discount();
}
~Sausage() {};
protected:
double calculate_cost()
{
cost = num_Hot_Dogs * 5.99 + num_Hot_Dog_Buns * 1.29 + num_Condiments * 0.79;
if (overnight_delivery) { cost += 9.00; }
if (insured) { cost *= 1.03; }
return cost;
}
};
class Albums :public Package
{
private:
int num_albums = 0;
int limited_edition = 0;
int signed_vinyl = 0;
public:
Albums(string location, int vinyls, bool express, bool insurance, int limited, int signature)
{
num_albums = vinyls;
name_and_address = location;
overnight_delivery = express;
insured = insurance;
limited_edition = limited;
signed_vinyl = signature;
package_contents = to_string(num_albums) + " Sia Vinyl Record(s), " +
(limited_edition > 0 ? to_string(limited_edition) + " Limited Edition Version(s) " : "") +
(signed_vinyl > 0 ? "and " + to_string(signed_vinyl) + " Signed by Sia herself " : "");
cost = calculate_cost();
discount = calculate_discount();
}
~Albums() {};
protected:
double calculate_cost()
{
cost = num_albums * 19.99 + signed_vinyl * 79.99 + limited_edition * 29.99;
if (overnight_delivery) { cost += 50.00; }
if (insured) { cost *= 1.25; }
return cost;
}
};
int main()
{
Video_Games a("Link LINKnKokiri ForestnKyoto, JAPAN 77547n", 4, true, false);
cout << a;
Genius_Phone b("Ada LOVELACEn1010 Binary StreetnLondon, ENGLAND 67859n", 1, true, false, 2);
cout << b;
Sausage c("Princess Annan2013 Disney RoadnArendelle, ALASKA 92684n", 350, false, true, 351, 4);
cout << c;
Albums d("David,n1326 90th Drive NEnEverett, WASHINGTON 98205n", 4, false, true, 2, 1);
cout << d;
return 0;
}

如果我正确理解了你的问题,那么你需要在基类中使用一个函数,它将调用派生类中的函数。在这种情况下,可以使用设计模式:模板方法。

class Package
{
public:
virtual double get_shipping_cost() = 0;
void PrintReceipt()
{
//some calulations
double shipcost = get_shipping_cost();
//use shipcost in printing the receipt      
}
};
class Video_Games : public Package
{
public:
double get_shipping_cost()
{
return 4.99;
}   
};
class Phones : public Package
{
public:
double get_shipping_cost()
{
return 6.78;
}   
};
// now you can print receipt as follows:
Package *pPackage = new Video_Games();
pPackage->PrintReceipt();
//OR
Video_Games a(....);
a.PrintReceipt();

我认为你在这里根本不需要派生类。

Package可以从为每个对象类别计算的值进行初始化。就在这里的例子中,我会让 etVideoGames是返回Packages 的自由函数。

每个都是类似的

Package VideoGames(string name_and_address, int number_of_games, bool express, bool insured)
{
string contents = to_string(number_of_games) + " Video Game(s)";
double subtotal = number_of_games * 19.99;
double shipping = 4.99;
double insurance_rate = 1.06
return Package(name_and_address, contents, subtotal, express, shipping, insured, insurance_rate);
}

Package将从这些参数中填写

你所要求的可以使用dynamic_cast来完成,例如:

class Package
{
...
double shipping_cost();
...
};
class Video_Games : public Package { ... };
class Genius_Phone : public Package { ... };
class Sausage : public Package { ... };
...
double Package::shipping_cost()
{
if (dynamic_cast<Video_Games*>(this) != NULL)
return 4.99;
if (dynamic_cast<Genius_Phone*>(this) != NULL)
return 25.00;
if (dynamic_cast<Sausage*>(this) != NULL)
return 9.00;
...
return 50.00;
}

但是,您的设计是错误的,并且非常不灵活。 添加更多类时,必须不断添加更多if语句。 随着时间的推移,这会减慢代码的速度,因为dynamic_cast调用运行时查找,因此会产生一些开销。

按照预期使用的方式使用多态性。 派生类中通用的所有功能都应位于基类中。基类需要的任何特定于类型的内容都应公开为可在派生类中重写的虚拟方法。

尝试更多类似的东西:

class Package
{
protected:
string name_and_address;
string package_contents;
bool overnight_delivery;
bool is_insured;
public:
Package(string location, bool express, bool insured)
: name_and_address(location), overnight_delivery(express), is_insured(insured)
{
}
virtual ~Package() {}
virtual double price() const = 0;
static double discount_rate(double cost) const
{
if (cost > 1000)
return 0.033;
if (cost > 500)
return 0.028;
if (cost > 200)
return 0.024;
return 0.019;
}
virtual double shipping_cost() const
{
return 50.00;
}
virtual double insurance_rate() const
{
return 1.0;
}
double calculate_cost() const
{
double cost = price();
if (overnight_delivery)
cost += shipping_cost();
if (is_insured)
cost *= insurance_rate();
return cost;
}
void print(ostream& out) const
{
chrono::system_clock::time_point now = chrono::system_clock::now();
time_t now_c = chrono::system_clock::to_time_t(now + chrono::hours(24));
chrono::system_clock::time_point now2 = chrono::system_clock::now();
time_t now2_c = chrono::system_clock::to_time_t(now2 + chrono::hours(72));
out << " *** BILL FOR GOODS ***" << endl;
out << "Customer: " << endl << endl;
out << name_and_address << endl;
out << (overnight_delivery ? (put_time(localtime(&now_c), "Expected Arrival Date: %F")) : put_time(localtime(&now2_c), "Expected Arrival Date: %F")) << endl << endl;
out << package_contents << endl;
out << (is_insured ? "{INSURED}" : "{NOT INSURED}") << endl;
out << (overnight_delivery ? "Expedited Shipping" : "Standard Shipping") << endl;
double cost = calculate_cost();
double rate = discount_rate(cost);
double discount = cost * rate;
out << setprecision(2) << showpoint << fixed;
out << "Shipping: $" << shipping_cost() << endl;
out << "Total Cost is: $" << cost << endl;
out << "Discount Percentage is: " << rate * 100 << "%" << " for a discount of $" << discount << endl;
out << "Total Cost after discount is $" << cost - discount << endl << endl;
}
};
ostream& operator<<(ostream &out, const Package &Package_Instance)
{
Package_Instance.print(out);
return out;
}
class Video_Games : public Package
{
private:
int num_games;
public:
Video_Games(string location, int number_of_games, bool express, bool insured)
: Package(location, express, insured), num_games(number_of_games)
{
package_contents = to_string(num_games) + " Video Game(s)";
}
virtual double price() const
{
return num_games * 19.99;
}
virtual double shipping_cost() const
{
return 4.99;
}
virtual double insurance_rate() const
{
return 1.06;
}
};
class Genius_Phone : public Package
{
private:
int num_phones;
int num_cases;
public:
Genius_Phone(string location, int number_of_phones, bool express, bool insured, int number_of_cases)
: Package(location, express, insured), num_phones(number_of_phones), num_cases(number_of_cases)
{
package_contents = to_string(num_phones) + " Genius Phone(s), " + (num_cases > 0 ? "and " + to_string(num_cases) + " cases " : "");
}
virtual double price() const
{
return (num_phones * 699.99) + (num_cases * 24.99);
}
virtual double shipping_cost() const
{
return 25.00;
}
virtual double insurance_rate() const
{
return 1.11;
}
};
class Sausage : public Package
{
private:
int num_Hot_Dogs;
int num_Condiments;
int num_Hot_Dog_Buns; 
public:
Sausage(string location, int hotdogs, bool express, bool insured, int condiments, int buns)
: Package(location, express, insured), num_Hot_Dogs(hotdogs), num_Condiments(condiments), num_Hot_Dog_Buns(buns)
{
package_contents = to_string(num_Hot_Dogs) + " Hot Dog(s), " + (num_Condiments > 0 ? to_string(num_Condiments) + " Condiment(s) " : "") + (num_Hot_Dog_Buns > 0 ? "and " + to_string(num_Hot_Dog_Buns) + " Hot Dog Bun(s) " : "");
}
virtual double price() const
{
return (num_Hot_Dogs * 5.99) + (num_Hot_Dog_Buns * 1.29) + (num_Condiments * 0.79);
}
virtual double shipping_cost() const
{
return 9.00;
}
virtual double insurance_rate() const
{
return 1.03;
}
};
class Albums : public Package
{
private:
int num_albums;
int limited_edition;
int signed_vinyl;
public:
Albums(string location, int vinyls, bool express, bool insured, int limited, int signature)
: Package(location, express, insured), num_albums(vinyls), limited_edition(limited), signed_vinyl(signature)
{
package_contents = to_string(num_albums) + " Sia Vinyl Record(s), " + (limited_edition > 0 ? to_string(limited_edition) + " Limited Edition Version(s) " : "") + (signed_vinyl > 0 ? "and " + to_string(signed_vinyl) + " Signed by Sia herself " : "");
}
virtual double price() const
{
return (num_albums * 19.99) + (signed_vinyl * 79.99) + (limited_edition * 29.99);
}
virtual double shipping_cost() const
{
return 50.00;
}
virtual double insurance_rate() const
{
return 1.25;
}
};