《C++ Primer Plus》中的编程练习
第12章 类和动态内存分配
1
在类的构造函数中使用动态内存分配时,若在默认构造函数中将指向动态分配内存的指针初始化为nulptr(空指针),则在方法中需要注意对空指针的判断。否则由默认构造函数初始化的对象调用方法时,将引发错误。
Cow::Cow() { name[0] = '\0'; hobby = nullptr; // 空指针 weight = 0.0; } Cow& Cow::operator=(const Cow& c) { if (this == &c) { return *this; } if (hobby != nullptr) // 对空指针的判断 { delete[] hobby; } hobby = new char[strlen(c.hobby) + 1]; strcpy_s(name, 20, c.name); strcpy_s(hobby, (strlen(c.hobby) + 1), c.hobby); weight = c.weight; return *this; } void Cow::ShowCow() const { if (hobby == nullptr) // 对空指针的判断 { std::cout << "This Cow's info is Empty!" << std::endl; return; } else { std::cout << "This is Information of COW." << std::endl; std::cout << "Name: " << name << std::endl; std::cout << "Hobby: " << hobby << std::endl; std::cout << "Weight: " << weight << std::endl; } }
strlen()函数返回字符串的长度,但不包括末尾的空字符。
sizeof()返回类型或变量的长度,单位为字节。
2
静态数据成员有一个特点,无论创建了多少对象,程序都只创建一个静态变量副本,也就是说,类的所有对象共享同一个静态成员。不能在类声明中初始化静态成员变量,因为类声明描述了如何分配内存,但并不分配内存(即可以使用这种格式来创建对象,从而分配和初始化内存)。对于静态类成员,可以在类声明之外使用单独的语句来进行初始化,这是因为静态类成员是单独存储的,而不是对象的组成部分。初始化语句指出了类型,并使用了作用域运算符,但没有使用关键字static。初始化是在方法文件中,而不是在类声明文件中进行的。如果在头文件中进行初始化,将出现读个初始化语句副本,从而引发错误。如果静态成员是const整数类型或枚举型,则可以在类声明中初始化。
静态成员函数声明中必须包含关键字static,但函数定义中(非内联情况下)不能包含关键字static。在公有部分声明的静态成员函数可以使用类名和作用域解析运算符来调用它。由于静态成员函数不与特定的对象相关联,因此只能使用静态数据成员。
将加法(或其他定义为成员函数或友元均可实现的运算符重载函数)定义为友元可以让程序更适应自动类型转换,原因是两个操作数都称为函数参数,因此与函数原型匹配。
3