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

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.

主站蜘蛛池模板: 徐汇区| 黄梅县| 彰武县| 马山县| 枝江市| 龙海市| 绥宁县| 洪泽县| 积石山| 贡嘎县| 古蔺县| 方城县| 安吉县| 阿拉善右旗| 云南省| 永新县| 巴林左旗| 和政县| 宁晋县| 东阳市| 安溪县| 剑川县| 博野县| 保康县| 阳东县| 宜都市| 扶风县| 塘沽区| 双鸭山市| 安溪县| 莱西市| 桃源县| 绥宁县| 鄂州市| 新乡县| 汕尾市| 沂源县| 长泰县| 余江县| 五莲县| 通化县|