官术网_书友最值得收藏!

Mimicking a class

A struct allows us to group variables, name them, and create objects. The idea of a class is to include the corresponding operations in the object, grouping both data and operations that are applicable to that particular data. For example, for the object of the Product type, it will be natural to call the set_rating() function on the object directly, rather than having a separate global function that takes a Product object via a pointer and modifies it. However, as we agreed to use structs in the C manner, we can't afford it to have member functions. To mimic a class using a C struct, we have to declare functions that work with the Product object as global functions, as shown in the following code:

struct Product {
std::string name;
double price;
int rating;
bool available;
};

void initialize(Product* p) {
p->price = 0.0;
p->rating = 0;
p->available = false;
}

void set_name(Product* p, const std::string& name) {
p->name = name;
}

std::string get_name(Product* p) {
return p->name;
}

void set_price(Product* p, double price) {
if (price < 0 || price > 9999.42) return;
p->price = price;
}

double get_price(Product* p) {
return p->price;
}

// code omitted for brevity

To use the struct as a class, we should manually call the functions in the proper order. For example, to use the object with properly initialized default values, we have to call the initialize() function first:

int main() {
Product cpp_book;
initialize(&cpp_book);
set_name(&cpp_book, "Mastering C++ Programming");
std::cout << "Book title is: " << get_name(&cpp_book);
// ...
}

This seems doable, but the preceding code will quickly turn into an unorganized mess if new types are added. For example, consider the Warehouse struct that keeps track of products:

struct Warehouse {
Product* products;
int capacity;
int size;
};

void initialize_warehouse(Warehouse* w) {
w->capacity = 1000;
w->size = 0;
w->products = new Product[w->capacity];
for (int ix = 0; ix < w->capacity; ++ix) {
initialize(&w->products[ix]); // initialize each Product object
}
}

void set_size(int size) { ... }
// code omitted for brevity

The first obvious issue is the naming of functions. We had to name the initializer function of the Warehouse initialize_warehouse to avoid conflict with the already declared initialize() function for the Product. We might consider renaming the functions for the Product type to avoid possible conflicts in the future. Next comes the mess with functions. Now, we have a bunch of global functions, which will increase in number as we add new types. It will be even more unmanageable if we add some hierarchy of types.

Though compilers tend to translate classes into structs with global functions, as we showed earlier, C++ and other high-level programming languages solve these and other issues that had not been mentioned by, introducing classes with smooth mechanisms of organizing them into hierarchies. Conceptually, keywords (class, public, or private) and mechanisms (inheritance and polymorphism) are there for developers to conveniently organize their code, but won't make the life of the compiler any easier.

主站蜘蛛池模板: 临猗县| 宜州市| 株洲县| 长宁县| 十堰市| 南郑县| 大港区| 镇沅| 车险| 闻喜县| 大英县| 晋宁县| 运城市| 海原县| 和林格尔县| 柯坪县| 山阴县| 灵丘县| 偏关县| 马关县| 富宁县| 井冈山市| 济源市| 马尔康县| 墨玉县| 夏河县| 蓝山县| 正安县| 宁强县| 仁化县| 孟津县| 如皋市| 阜南县| 涡阳县| 翼城县| 富民县| 眉山市| 商丘市| 凤阳县| 浦东新区| 大宁县|